home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 34 / Amiga Format CD34 (1998-11-20)(Future Publishing)(GB)[!][Christmas issue].iso / -seriously_amiga- / programming / c / viewperf5.1 / viewperf / objs / viewperf.c < prev    next >
C/C++ Source or Header  |  1998-10-01  |  142KB  |  4,108 lines

  1. /*
  2. // Permission to use, copy, modify, and distribute this software and its
  3. // documentation for any purpose and without fee is hereby granted, provided
  4. // that the above copyright notice appear in all copies and that both that
  5. // copyright notice and this permission notice appear in supporting
  6. // documentation, and that the name of I.B.M. not be used in advertising
  7. // or publicity pertaining to distribution of the software without specific,
  8. // written prior permission. I.B.M. makes no representations about the
  9. // suitability of this software for any purpose.  It is provided "as is"
  10. // without express or implied warranty.
  11. //
  12. // I.B.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  13. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL I.B.M.
  14. // BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  15. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  16. // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  17. // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  18. //
  19. // Author:  Barry Minor, IBM AWS Graphics Systems (Austin)
  20. //          minor@austin.ibm.com
  21. //
  22. // Special Thanks to ..
  23. //
  24. //          John Dennis      of DEC
  25. //          Bob Arenburg     of IBM
  26. //          Rob Putney       of IBM
  27. //          Dale Kirkland    of Intergraph
  28. //          Hock Lee         of Microsoft
  29. //          Tom McReynolds   of SGI
  30. //          John Spitzer     of SGI
  31. //
  32. // and the OPC committee
  33. // for their help in completing this project
  34. */
  35.  
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <fcntl.h>
  41. #ifdef CRAY
  42. #include <rpc/types.h>
  43. #include <rpc/xdr.h>
  44. #endif
  45. #if defined(OS2) || defined(WIN32)
  46. #include <stdarg.h>
  47. #else
  48. #include <unistd.h>
  49. #endif
  50. #include <math.h>
  51. #include <stdlib.h>
  52. #ifdef WIN32
  53. #include <windows.h>
  54. #endif
  55. #include <GL/gl.h>
  56. #if defined(WIN32) || defined(__amigaos__)
  57. #include <GL/glaux.h>
  58. #else
  59. #include "aux.h"
  60. #endif
  61. #include "viewperf.h"
  62. #include "bfont.h"
  63. #include "vpProtos.h"
  64. #include "plyJT.h"
  65. #include "mshJT.h"
  66. #include "triJT.h"
  67. #include "qadJT.h"
  68. #include "evtJT.h"
  69. #include "Env.h"
  70.  
  71. #ifdef WIN32
  72. static FILE *LogFile;
  73. #endif
  74.  
  75. #if defined(WIN32) || defined(OS2)
  76. #define BINARY_FILE "rb"
  77. #else
  78. #define BINARY_FILE "r"
  79. #endif
  80.  
  81. #ifdef __hpux
  82. #include "limits.h"
  83. #endif
  84.  
  85. #ifdef MP
  86. int numProcessors ();
  87. #endif
  88.  
  89. /* Function Pointers */
  90. void    (*eventloop)(int thread);
  91. void fill_mesh(struct mesh *msh, FILE *f,
  92. GLenum swapFlag, float *min, float *max);
  93. void read_colors(struct colorvector * vcolor, FILE *f);
  94. void calculate_colors(struct colorvector * vcolor, struct vector * verts,
  95. GLfloat * trans, GLfloat maxmag, GLfloat minmag);
  96. void compare_min_max(struct vector * verts, GLfloat * trans, 
  97. GLfloat *minmag, GLfloat *maxmag);
  98. void compute_bounds(GLfloat *center, GLfloat *trans, 
  99. GLfloat *min, GLfloat *max);
  100. void get_colors_msh(struct mesh *msh, int np, 
  101. GLfloat *trans, char *objnameptr);
  102. void get_colors_ply(struct vector *vert, struct colorvector *vcolor, 
  103. int numverts, GLfloat *trans, char *objnameptr);
  104. void get_colors_triquad(struct vector *vert, struct colorvector *vcolor, 
  105. int numverts, GLfloat *trans, char *objnameptr);
  106.  
  107.  
  108. /* Global Variables */
  109. struct    EventBlock eventblock;
  110. GLfloat iang=0.0, jang=0.0, kang=0.0;
  111.  
  112. char    rendermodetext[][16] = {
  113.     "TMESH",
  114.     "VECTOR",
  115.     "LINE",
  116.     "POINT",
  117.     "POLYGON",
  118.     "TFAN",
  119.     "TRIANGLE",
  120.     "QUAD"
  121. };
  122.  
  123.  
  124. int    BatchTable[] = {
  125.     BM_NO_BATCH,         /* TMESHmode   */
  126.     BM_BATCH_BY_TWO,     /* VECTORmode  */
  127.     BM_NO_BATCH,         /* LINEmode    */
  128.     BM_BATCH_ALL,         /* POINTmode   */
  129.     BM_NO_BATCH,         /* POLYGONmode */
  130.     BM_NO_BATCH,         /* TFANmode    */
  131.     BM_BATCH_ALL,         /* TRImode     */
  132.     BM_BATCH_ALL         /* QUADmode    */
  133. };
  134.  
  135.  
  136. /*********************************************************************/
  137. /*                                                                   */
  138. /*                   text strings for reporting                      */
  139. /*                                                                   */
  140. /*********************************************************************/
  141.  
  142. char    txfile[100] = "NONE";
  143. char    txmin[30]   = "NEAREST";
  144. char    txmag[30]   = "NEAREST";
  145. char    txenv[30]   = "DECAL";
  146.  
  147. char    txsblendfunc[40]   = "SRC_ALPHA";
  148. char    txdblendfunc[40]   = "ONE_MINUS_SRC_ALPHA";
  149.  
  150. char    txtoggle[40] = "NONE";
  151.  
  152. char    txcriteria[10] = "MINIMUM";
  153.  
  154. char    txpmf[10]   = "FILL";
  155. char    txpmb[10]   = "FILL";
  156.  
  157. char    txcolormode[30]   = "COLOR_PER_FRAME";
  158.  
  159. char    teststring[][32] = {
  160.     "FRAME",
  161.     "PRIMITIVE",
  162.     "VERTEX"
  163. };
  164.  
  165.  
  166. char    extension[][8] = {
  167.     ".coo",
  168.     ".ele",
  169.     ".vnm",
  170.     ".clr",
  171.     ".msh",
  172.     ".bin",
  173.     ".wlk"
  174. };
  175.  
  176.  
  177. char    falsetrue[][8] = {
  178.     "FALSE",
  179.     "TRUE"
  180. };
  181.  
  182. char     texture_generation_mode[][32] = {
  183.     "NO_TEXTURE_GENERATION",
  184.     "EYE_LINEAR",
  185.     "OBJECT_LINEAR",
  186.     "SPHERE_MAP"
  187. };
  188.  
  189. char cmfaceString[64] = "FRONT";
  190. char cmmodeString[64] = "AMBIENT_AND_DIFFUSE";
  191.  
  192. static char cmdln[400];
  193. static char desc[400];
  194.  
  195. /* text for test description */
  196. static char *bf[]    = {
  197.     ""       , "-bf "  };
  198. static char *ff[]    = {
  199.     ""       , "-ff "  };
  200. static char *ls[]    = {
  201.     ""       , "-ls "  };
  202. static char *fn[]    = {
  203.     ""       , "-fn "  };
  204. static char *dl[]    = {
  205.     ""       , "-dl "  };
  206. static char *shade[] = {
  207.     ""       , "-f "   };
  208. static char *dr[]    = {
  209.     "-ir "   , ""      };
  210. static char *vac[]   = {
  211.     ""       , "-vac " };
  212. static char *val[]   = {
  213.     ""       , "-val " };
  214. static char *vz[]    = {
  215.     ""       , "-vz "  };
  216. static char *vst[]   = {
  217.     ""       , "-vst " };
  218. static char *db[]    = {
  219.     "-sb "   , ""      };
  220. static char *or[]    = {
  221.     ""       , "-or "  };
  222. static char *di[]    = {
  223.     "-ndi"       , ""  };
  224. static char *bl[]    = {
  225.     ""       , "-bl "  };
  226. static char *zb[]    = {
  227.     ""       , "-zb "  };
  228. static char *lp[]    = {
  229.     ""       , "-lp "  };
  230. static char *pp[]    = {
  231.     ""       , "-pp "  };
  232. static char *fg[]    = {
  233.     ""       , "-fg "  };
  234. static char *clip[]  = {
  235.     ""       , "-c "   };
  236. static char *l2s[]   = {
  237.     ""       , "-l2s " };
  238. static char *lv[]    = {
  239.     ""       , "-lv "  };
  240. static char *ll[]    = {
  241.     ""       , "-ll "  };
  242. static char *ps[]    = {
  243.     ""       , "-ps "  };
  244. static char *cptx[] = {
  245.     "FRAME ", "PRIMITIVE ", "VERTEX "};
  246. static char *inputmodetx[] = {
  247.     "", "-pg ", "-mh ", "-tr ", "-qd "};
  248.  
  249.  
  250. static unsigned int    stipple[32] = {
  251.     0xAAAAAAAA,
  252.     0x55555555,
  253.     0xAAAAAAAA,
  254.     0x55555555,
  255.     0xAAAAAAAA,
  256.     0x55555555,
  257.     0xAAAAAAAA,
  258.     0x55555555,
  259.     0xAAAAAAAA,
  260.     0x55555555,
  261.     0xAAAAAAAA,
  262.     0x55555555,
  263.     0xAAAAAAAA,
  264.     0x55555555,
  265.     0xAAAAAAAA,
  266.     0x55555555,
  267.     0xAAAAAAAA,
  268.     0x55555555,
  269.     0xAAAAAAAA,
  270.     0x55555555,
  271.     0xAAAAAAAA,
  272.     0x55555555,
  273.     0xAAAAAAAA,
  274.     0x55555555,
  275.     0xAAAAAAAA,
  276.     0x55555555,
  277.     0xAAAAAAAA,
  278.     0x55555555,
  279.     0xAAAAAAAA,
  280.     0x55555555,
  281.     0xAAAAAAAA,
  282.     0x55555555
  283. };
  284.  
  285. static GLfloat maxdim;
  286. static int    vertsperframe;
  287.  
  288.  
  289. #if defined(WIN32)
  290. void APIENTRY FinishFrame(HDC hdc)
  291. {
  292.         glFinish();
  293. }
  294. #elif defined(OS2) || defined(__amigaos__)
  295. void FinishFrame(void)
  296. {
  297.         glFinish();
  298. }
  299. #else
  300. void FinishFrame(Display *dpy, GLXDrawable drawable)
  301. {
  302.         glFinish();
  303. }
  304. #endif
  305.  
  306. /*********************************************************************/
  307. /*                                                                   */
  308. /*  Swap for all you LITTLE_ENDIAN fans out there                    */
  309. /*  Use this to convert binary files to LITTLE_ENDIAN format         */
  310. /*                                                                   */
  311. /*********************************************************************/
  312.  
  313. void    Swap32(void *ptr, long length)
  314. {
  315.     register GLuint tmp;        /* GLuint should be typedef'ed to 32 bit
  316.                                    unsigned int */
  317.     GLuint i, *array = (GLuint * ) ptr;
  318.  
  319.     for (i = 0; i < length; i++) {
  320.         tmp = array[i];
  321.         tmp &= 0xffffffff;
  322.         tmp = ((tmp >> 24) | (tmp << 24) | 
  323.             ((tmp >> 8) & 0xff00) | ((tmp << 8) & 0xff0000));
  324.         array[i] = tmp;
  325.     }
  326.  
  327. }
  328.  
  329.  
  330. /*********************************************************************/
  331. /*                                                                   */
  332. /*  Convert GL error enums to text strings for output                */
  333. /*                                                                   */
  334. /*********************************************************************/
  335.  
  336. char    *error2str(GLenum err)
  337. {
  338.     switch (err) {
  339.     case GL_INVALID_ENUM:
  340.         return("GL_INVALID_ENUM");
  341.     case GL_INVALID_VALUE:
  342.         return("GL_INVALID_VALUE");
  343.     case GL_INVALID_OPERATION:
  344.         return("GL_INVALID_OPERATION");
  345.     case GL_STACK_OVERFLOW:
  346.         return("GL_STACK_OVERFLOW");
  347.     case GL_STACK_UNDERFLOW:
  348.         return("GL_STACK_UNDERFLOW");
  349.     case GL_OUT_OF_MEMORY:
  350.         return("GL_OUT_OF_MEMORY");
  351.     }
  352. }
  353.  
  354.  
  355. /*********************************************************************/
  356. /*                                                                   */
  357. /*  Convert HSV color space to RGB                                   */
  358. /*  Used to create vertex colors for data sets                       */
  359. /*                                                                   */
  360. /*********************************************************************/
  361.  
  362. hsv_to_rgb(GLfloat h, GLfloat s, GLfloat v, GLfloat *r, GLfloat *g, GLfloat *b)
  363. {
  364.     int    i;
  365.     GLfloat       f, p, q, t;
  366.  
  367.     if (s == 0.0) {
  368.         *r = v;
  369.         *g = v;
  370.         *b = v;
  371.     } else {
  372.         h = fmod(h, 1.);
  373.         h *= 6.;
  374.         i = (int) floor(h);
  375.         f = h - i;
  376.         p = v * (1 - s);
  377.         q = v * (1 - (s * f));
  378.         t = v * (1 - (s * (1 - f)));
  379.         switch (i) {
  380.         case 0 :
  381.             *r = v;
  382.             *g = t;
  383.             *b = p;
  384.             break;
  385.         case 1 :
  386.             *r = q;
  387.             *g = v;
  388.             *b = p;
  389.             break;
  390.         case 2 :
  391.             *r = p;
  392.             *g = v;
  393.             *b = t;
  394.             break;
  395.         case 3 :
  396.             *r = p;
  397.             *g = q;
  398.             *b = v;
  399.             break;
  400.         case 4 :
  401.             *r = t;
  402.             *g = p;
  403.             *b = v;
  404.             break;
  405.         case 5 :
  406.             *r = v;
  407.             *g = p;
  408.             *b = q;
  409.             break;
  410.         }
  411.     }
  412. }
  413.  
  414. #ifdef SEARCHPATH
  415. /*********************************************************************/
  416. /*                                                                   */
  417. /*  Find a path of a particular file                                 */
  418. /*                                                                   */
  419. /*********************************************************************/
  420.  
  421. char* SearchPath(const char* path, const char* file)
  422. {
  423.     static char fullpath[512];
  424.     char filename[512];
  425.     char* tmppath;
  426.     char searchpath[512];
  427.     FILE *f;
  428.  
  429.     strcpy(searchpath, path);
  430.     for (tmppath = strtok(searchpath, ":"); tmppath; tmppath = strtok(NULL, ":")) {
  431.         if (*tmppath == 0) {
  432.             strcpy(filename, ".");
  433.         } else {
  434.             strcpy(filename, tmppath);
  435.         }
  436.         strcat(filename, "/");
  437.         strcat(filename, file);
  438.         if (f = fopen(filename, "r")) {
  439.             fclose(f);
  440.             strcpy(fullpath, tmppath);
  441.             return fullpath;
  442.         }
  443.     }
  444.     return NULL;
  445. }
  446. #endif
  447.  
  448. /*********************************************************************/
  449. /*                                                                   */
  450. /*  Compute texture coordinates for polygon data sets                */
  451. /*  Creates a spherical mapping based on vertex normals              */
  452. /*                                                                   */
  453. /*********************************************************************/
  454.  
  455. int    param_poly(struct EventBlock *pevent)
  456. {
  457.     int    i;
  458.     double    phi, theta;
  459.     double    basex, basey, basemag;
  460.     double    uu, ww;
  461.     struct vector *texture;
  462.     struct vector *vnorm = pevent->rb->vnorm;
  463.     int    numverts = pevent->rb->numverts;
  464.  
  465.     texture = pevent->rb->texture = (struct vector *)malloc((numverts + 1) * sizeof(struct vector ));
  466.  
  467.     for (i = 1; i <= numverts; i++) {
  468.         /* calculate location in texture map */
  469.         phi = acos(((double) vnorm[i].z));
  470.         basemag = sqrt((double)vnorm[i].x * (double)vnorm[i].x + 
  471.             (double)vnorm[i].y * (double)vnorm[i].y);
  472.         if (basemag == 0.0) {
  473.             basex = 0.0;
  474.             basey = 0.0;
  475.         } else {
  476.             basex = vnorm[i].x / basemag;
  477.             basey = vnorm[i].y / basemag;
  478.         }
  479.         theta = asin((double)basey);
  480.         if (basex < 0.0)
  481.             theta = PI - theta;
  482.         if (theta < 0.0)
  483.             theta += 2.0 * PI;
  484.         uu = theta / (2.0 * PI);
  485.         ww = phi / (PI);
  486.         texture[i].x = (GLfloat)uu;
  487.         texture[i].y = (GLfloat)ww;
  488.     }
  489. }
  490.  
  491.  
  492. /*********************************************************************/
  493. /*                                                                   */
  494. /*  Compute texture coordinates for mesh data sets                   */
  495. /*  Creates a spherical mapping based on vertex normals              */
  496. /*                                                                   */
  497. /*********************************************************************/
  498.  
  499. int    param_mesh(struct EventBlock *pevent)
  500. {
  501.     int    i, k;
  502.     GLfloat phi, theta;
  503.     double    basex, basey, basemag;
  504.     GLfloat uu, ww;
  505.     struct mesh *msh = pevent->rb->msh;
  506.     struct vector *norms;
  507.     struct vector *texture;
  508.     int    *np = &pevent->rb->np;
  509.  
  510.     for (i = 0; i < *np; i++) {
  511.         norms = msh[i].norms;
  512.         texture = msh[i].texture;
  513.         for (k = 0; k < msh[i].numverts; ++k) {
  514.             /* calculate location in texture map */
  515.             phi = acos((double)norms[k].z);
  516.             basemag = sqrt((double)norms[k].x * (double)norms[k].x + (double)norms[k].y * (double)norms[k].y);
  517.             if (basemag == 0.0) {
  518.                 basex = 0.0;
  519.                 basey = 0.0;
  520.             } else {
  521.                 basex = msh[i].norms[k].x / basemag;
  522.                 basey = msh[i].norms[k].y / basemag;
  523.             }
  524.             theta = asin((double)basey);
  525.             if (basex < 0.0)
  526.                 theta = PI - theta;
  527.             if (theta < 0.0)
  528.                 theta += 2.0 * PI;
  529.             uu = theta / (2.0 * PI);
  530.             ww = phi / (PI);
  531.             texture[k].x = (GLfloat)uu;
  532.             texture[k].y = (GLfloat)ww;
  533.         }
  534.     }
  535. }
  536.  
  537.  
  538. /*********************************************************************/
  539. /*                                                                   */
  540. /*  meshinput reads in mesh data sets and computes vertex data       */
  541. /*                                                                   */
  542. /*********************************************************************/
  543.  
  544. void    meshinput(char *objnameptr, struct EventBlock *pevent)
  545. {
  546.     union {
  547.         int    testWord;
  548.         char    testByte[4];
  549.     } endianTest;
  550.     GLenum swapFlag;
  551.     int binary_version, datatype;
  552.     int    i, k;
  553.     int    nummesh;
  554.     FILE * f;
  555.     char    filename[512], *filenameptr;
  556.     int    tempspace[100];
  557.     GLfloat maxmag, minmag, vertmag;
  558.     GLfloat tmp;
  559.     int cvcount;
  560.     int    nRead;
  561.     struct vector *dummybuffer;
  562.     GLfloat * trans = pevent->trans;
  563.     GLfloat * center = pevent->center;
  564.     struct mesh *msh;
  565.     int    *np = &pevent->rb->np;
  566.     float    max[3], min[3];
  567. #ifdef CRAY
  568.     XDR xdr_handle;
  569.     XDR *xdrs = &xdr_handle;
  570.     float fbuf[3];
  571. #endif
  572.  
  573.     endianTest.testWord = 1;
  574.     if (endianTest.testByte[0] == 1) {
  575.         swapFlag = GL_TRUE;
  576.     } else {
  577.         swapFlag = GL_FALSE;
  578.     }
  579.     *np = 0;
  580.  
  581.     filenameptr = filename;
  582.  
  583.     for (i = 0; i < 3; i++) {
  584.         max[i] = SMALL;
  585.         min[i] = BIG;
  586.     }
  587.  
  588.     filenameptr = strcpy(filenameptr, objnameptr);
  589.     /* Check to see if binary file format is present */
  590.     filenameptr = strcat(filenameptr, extension[5]);
  591.  
  592.     if ((f = fopen(filename, BINARY_FILE)))
  593.     {
  594.         nRead = fread(&binary_version, sizeof(unsigned int), 1, f);
  595.         if(nRead == 0) {
  596.             FATAL_ERROR("unexpected end of input in binary file\n");
  597.         }
  598.         switch(binary_version) {
  599.         case 0:
  600.             nRead = fread(&datatype, sizeof(GLenum),1,f);
  601.             if(nRead != 1) FATAL_ERROR("Unexpected end of input\n");
  602.             if(datatype != GL_TRIANGLE_STRIP)
  603.             {
  604.                 FATAL_ERROR("primitive type is not a triangle mesh\n");
  605.             }
  606.             nRead = fread(np, sizeof(int), 1, f);
  607.             if(nRead != 1) FATAL_ERROR("Unexpected end of input\n");
  608.  
  609.             msh = pevent->rb->msh = 
  610.                 (struct mesh*)malloc(*np *sizeof(struct mesh));
  611.  
  612. #ifdef CRAY
  613.             xdrstdio_create(xdrs, f, XDR_DECODE);
  614. #endif
  615.             for(nummesh = 0; nummesh < *np; ++nummesh)
  616.             {
  617.                 fill_mesh(&(msh[nummesh]), f, swapFlag, min, max);
  618.             }
  619. #ifdef CRAY
  620.             xdr_destroy(xdrs);
  621. #endif
  622.             fclose(f);
  623.  
  624.             compute_bounds(center, trans, min, max);
  625.             get_colors_msh(msh, *np, trans, objnameptr);
  626.             break;
  627.  
  628.         default:
  629.             printf("Unrecognized binary version %u", binary_version);
  630.             exit(1);
  631.             break;
  632.         }
  633.     } else {
  634.         filenameptr = strcpy(filenameptr, objnameptr);
  635.         filenameptr = strcat(filenameptr, extension[4]);
  636.  
  637.         if((f = fopen(filename, BINARY_FILE)) == NULL) {
  638.             printf("Couldn't open (.msh) input file %s\n", filename);
  639.             exit(1);
  640.         }
  641.  
  642.         /* Read through one to get a count */
  643.  
  644. #ifndef CRAY
  645.         while ((nRead = fread(&cvcount, sizeof(GLint), 1, f)) > 0) {
  646.             if (swapFlag)
  647.                 Swap32((void *) & cvcount, 1);
  648.             dummybuffer = (struct vector *) malloc(cvcount * sizeof(struct vector ));
  649.  
  650.             nRead = fread(dummybuffer, cvcount * sizeof(GLfloat) * 3, 1, f);
  651.             if (nRead == 0) {
  652.                 FATAL_ERROR("unexpected end of input in .msh file\n");
  653.             }
  654.             if (nRead < 0) {
  655.                 FATAL_ERROR("read error getting mesh\n");
  656.             }
  657.             nRead = fread(dummybuffer, cvcount * sizeof(GLfloat) * 3, 1, f);
  658.             if (nRead == 0) {
  659.                 FATAL_ERROR("unexpected end of input\n");
  660.             }
  661.             if (nRead < 0) {
  662.                 FATAL_ERROR("read error getting mesh\n");
  663.             }
  664.             free(dummybuffer);
  665.             (*np)++;
  666.         }
  667.         if (nRead < 0)
  668.         {
  669.             FATAL_ERROR("read error getting mesh\n");
  670.         }
  671. #else
  672.         xdrstdio_create(xdrs, f, XDR_DECODE);
  673.         while (xdr_int(xdrs, &cvcount)) {
  674.             for (i = 0; i < cvcount; i++) {
  675.                 if (!xdr_vector(xdrs, (void *)&fbuf, 3, sizeof(float), xdr_float)) {
  676.                     FATAL_ERROR("unexpected end of input\n");
  677.                 }
  678.                 if (!xdr_vector(xdrs, (void *)&fbuf, 3, sizeof(float), xdr_float)) {
  679.                     FATAL_ERROR("unexpected end of input\n");
  680.                 }
  681.             }
  682.             (*np)++;
  683.         }
  684.         xdr_destroy(xdrs);
  685. #endif
  686.         fclose(f);
  687.  
  688.         if((f = fopen(filename, BINARY_FILE)) == 0) {
  689.             FATAL_ERROR("Couldn't open (msh) input file\n");
  690.         }
  691.         /* malloc space for structure and fill it in */
  692.         msh = pevent->rb->msh = 
  693.             (struct mesh *)malloc(*np * sizeof(struct mesh ));
  694.  
  695. #ifdef CRAY
  696.         xdrstdio_create(xdrs, f, XDR_DECODE);
  697. #endif
  698.         for (nummesh = 0; nummesh < *np; ++nummesh) {
  699.             fill_mesh(&(msh[nummesh]), f, swapFlag, min, max);
  700.         }
  701.  
  702. #ifdef CRAY
  703.         xdr_destroy(xdrs);
  704. #endif
  705.         fclose(f);
  706.  
  707.         /* Compute bounding box info for data set */
  708.  
  709.         compute_bounds(center, trans, min, max);
  710.  
  711.         /* Compute vertex colors */
  712.  
  713.         get_colors_msh(msh, *np, trans, objnameptr);
  714.  
  715.     }
  716.     /* count the number of vertex calls per frame */
  717.     vertsperframe = 0;
  718.     for (i = 0; i < *np; i++) {
  719.         vertsperframe += msh[i].numverts;
  720.     }
  721. }
  722.  
  723. void get_colors_msh(struct mesh *msh, int np, 
  724. GLfloat *trans, char *objnameptr)
  725. {
  726.     GLfloat maxmag = SMALL;
  727.     GLfloat minmag = BIG;
  728.     int i, k;
  729.     FILE *f;
  730.     char filename[512], *filenameptr;
  731.  
  732.     filenameptr = filename;
  733.  
  734.     filenameptr = strcpy(filenameptr, objnameptr);
  735.     filenameptr = strcat(filenameptr, extension[3]);
  736.  
  737.     if(f = fopen(filename, BINARY_FILE)) {
  738.         for (i = 0; i < np; i++) {
  739.             for (k = 0; k < msh[i].numverts; ++k) {
  740.                 read_colors(&(msh[i].vcolor[k]), f);
  741.             }
  742.         }
  743.         fclose(f);
  744.     } else {
  745.         for (i = 0; i < np; i++) {
  746.             for (k = 0; k < msh[i].numverts; ++k) {
  747.                 compare_min_max(&(msh[i].verts[k]), trans, &minmag, &maxmag);
  748.             }
  749.         }
  750.         for (i = 0; i < np; i++) {
  751.             for (k = 0; k < msh[i].numverts; ++k) {
  752.                 calculate_colors(&(msh[i].vcolor[k]), &(msh[i].verts[k]),
  753.                     trans, maxmag, minmag);
  754.             }
  755.         }
  756.     }
  757.  
  758. }
  759.  
  760.  
  761. void compute_bounds(GLfloat *center, GLfloat *trans, 
  762. GLfloat *min, GLfloat *max)
  763. {
  764.     center[0] = (max[0] - min[0]);
  765.     center[1] = (max[1] - min[1]);
  766.     center[2] = (max[2] - min[2]);
  767.  
  768.     maxdim = sqrt((double)(center[0] * center[0] + center[1] * center[1] + 
  769.         center[2] * center[2])) / 2.0F;
  770.     trans[3] = maxdim;
  771.  
  772.     center[0] /= 2.0F;   /* don't move look up - need half dim */
  773.     center[1] /= 2.0F;
  774.     center[2] /= 2.0F;
  775.     trans[0] = min[0] + center[0];
  776.     trans[1] = min[1] + center[1];
  777.     trans[2] = min[2] + center[2];
  778. }
  779.  
  780. void compare_min_max(struct vector * verts, GLfloat * trans, 
  781. GLfloat *minmag, GLfloat *maxmag)
  782. {
  783.     GLfloat vertmag;
  784.  
  785.     vertmag = sqrt((double)(verts->x - trans[0]) * 
  786.         (verts->x - trans[0]) + 
  787.         (verts->y - trans[1]) * 
  788.         (verts->y - trans[1]) + 
  789.         (verts->z - trans[2]) * 
  790.         (verts->z - trans[2]));
  791.     if (vertmag > *maxmag)
  792.         *maxmag = vertmag;
  793.     if (vertmag < *minmag)
  794.         *minmag = vertmag;
  795. }
  796.  
  797. void calculate_colors(struct colorvector * vcolor,  struct vector * verts,
  798. GLfloat * trans, GLfloat maxmag, GLfloat minmag)
  799. {
  800.     GLfloat r, g, b, d;
  801.     GLfloat vertmag;
  802.  
  803.     vertmag = sqrt((double)((verts->x - trans[0]) * 
  804.         (verts->x - trans[0]) + 
  805.         (verts->y - trans[1]) * 
  806.         (verts->y - trans[1]) + 
  807.         (verts->z - trans[2]) * 
  808.         (verts->z - trans[2])));
  809.     d = maxmag - vertmag;
  810.     if (d == 0.0)
  811.         vertmag = 1.0;
  812.     else
  813.         vertmag = (maxmag - minmag) / d;
  814.     hsv_to_rgb(vertmag, 1.0, 1.0, &r, &g, &b);
  815.     vcolor->r = r;
  816.     vcolor->g = g;
  817.     vcolor->b = b;
  818.     vcolor->a = 0.5;
  819. }
  820.  
  821.  
  822.  
  823. void read_colors(struct colorvector * vcolor, FILE *f)
  824. {
  825.     float r, g, b, a;
  826.     int nRead;
  827.  
  828.     nRead = 0;
  829.     nRead += fread(&r, sizeof(float), 1, f);
  830.     nRead += fread(&g, sizeof(float), 1, f);
  831.     nRead += fread(&b, sizeof(float), 1, f);
  832.     nRead += fread(&a, sizeof(float), 1, f);
  833.  
  834.     if(nRead != 4) {
  835.         FATAL_ERROR("read error in color file");
  836.     }
  837.  
  838. #ifdef LITTLE_ENDIAN
  839.     Swap32(&r, 1);
  840.     Swap32(&g, 1);
  841.     Swap32(&b, 1);
  842.     Swap32(&a, 1);
  843. #endif
  844.     vcolor->r = r;
  845.     vcolor->g = g;
  846.     vcolor->b = b;
  847.     vcolor->a = a;
  848. }
  849.  
  850.  
  851. void fill_mesh(struct mesh *msh, FILE *f, 
  852. GLenum swapFlag, float *min, float*max)
  853. {
  854.     int cvcount;
  855.     int i;
  856.  
  857. #ifndef CRAY
  858.     fread(&cvcount, sizeof(GLint), 1, f);
  859.     if (swapFlag)
  860.         Swap32((void *) & cvcount, 1);
  861. #else
  862.     xdr_int(xdrs, &cvcount);
  863. #endif
  864.     msh->numverts = cvcount;
  865.     msh->verts = (struct vector *) malloc(cvcount * sizeof(struct vector ));
  866.     msh->norms = (struct vector *) malloc(cvcount * sizeof(struct vector ));
  867.     msh->texture = (struct vector *) malloc(cvcount * sizeof(struct vector ));
  868.     msh->vcolor = (struct colorvector *) malloc(cvcount * sizeof(struct colorvector ));
  869. #ifndef CRAY
  870.     fread(&msh->verts[0].x, cvcount * sizeof(GLfloat) * 3, 1, f);
  871.     fread(&msh->norms[0].x, cvcount * sizeof(GLfloat) * 3, 1, f);
  872.     if (swapFlag) {
  873.         Swap32((void *) & msh->verts[0].x, cvcount * 3);
  874.         Swap32((void *) & msh->norms[0].x, cvcount * 3);
  875.     }
  876. #else
  877.     xdr_vector(xdrs, (void *)&msh->verts[0].x, cvcount * 3, sizeof(float), xdr_float);
  878.     xdr_vector(xdrs, (void *)&msh->norms[0].x, cvcount * 3, sizeof(float), xdr_float);
  879. #endif
  880.     for (i = 0; i < cvcount; i++) {
  881.         if (msh->verts[i].x > max[0])
  882.             max[0] = msh->verts[i].x;
  883.         else 
  884.             if (msh->verts[i].x < min[0])
  885.                 min[0] = msh->verts[i].x;
  886.  
  887.         if (msh->verts[i].y > max[1])
  888.             max[1] = msh->verts[i].y;
  889.         else 
  890.             if ( msh->verts[i].y < min[1])
  891.                 min[1] = msh->verts[i].y;
  892.  
  893.         if (msh->verts[i].z > max[2])
  894.             max[2] = msh->verts[i].z;
  895.         else 
  896.             if (msh->verts[i].z < min[2])
  897.                 min[2] = msh->verts[i].z;
  898.     }
  899. }
  900.  
  901.  
  902. /*********************************************************************/
  903. /*                                                                   */
  904. /*  polygoninput reads in polygon data sets and computes vertex data */
  905. /*                                                                   */
  906. /*********************************************************************/
  907.  
  908. void    polygoninput(char *objnameptr, struct EventBlock *pevent)
  909. {
  910.     int    i;
  911.     FILE * f;
  912.     int    numverts;
  913.     int    numpoly;
  914.     char    filename[512], *filenameptr;
  915.     int    tempspace[100];
  916.     GLfloat maxmag, minmag, vertmag;
  917.     GLfloat tmp;
  918.     char    name[1024];
  919.     int    nRead;
  920.     int    index, colorflag;
  921.     GLfloat dummy[3];
  922.     GLfloat * trans = pevent->trans;
  923.     GLfloat * center = pevent->center;
  924.     struct vector *vert;
  925.     struct vector *vnorm;
  926.     struct colorvector *vcolor;
  927.     struct plygon *ply;
  928.     int    *np = &pevent->rb->np;
  929.     float    max[3], min[3];
  930.     int binary_file = 0;
  931.     int binary_version, datatype;
  932.  
  933.     *np = 0;
  934.  
  935.     filenameptr = filename;
  936.  
  937.     for (i = 0; i < 3; i++) {
  938.         max[i] = SMALL;
  939.         min[i] = BIG;
  940.     }
  941.  
  942.     filenameptr = strcpy(filenameptr, objnameptr);
  943.     /* Check to see if binary file format is present */
  944.     filenameptr = strcat(filenameptr, extension[5]);
  945.  
  946.     if ((f = fopen(filename, BINARY_FILE))) {
  947.         binary_file = 1;
  948.         nRead = fread(&binary_version, sizeof(unsigned int), 1, f);
  949.         if(nRead == 0) {
  950.             FATAL_ERROR("unexpected end of input in binary file\n");
  951.         }
  952.         switch(binary_version) {
  953.         case 0:
  954.             nRead = fread(&datatype, sizeof(GLenum),1,f);
  955.             if(nRead != 1) FATAL_ERROR("Unexpected end of input\n");
  956.             if(datatype != GL_POLYGON) {
  957.                 FATAL_ERROR("primitive type is not a polygon\n");
  958.             }
  959.  
  960.             nRead = fread(np, sizeof(int), 1, f);
  961.             if(nRead != 1) FATAL_ERROR("Unexpected end of input\n");
  962.  
  963.             ply = pevent->rb->ply = 
  964.                 (struct plygon *)malloc((*np) * sizeof(struct plygon ));
  965.  
  966.             for(numpoly = 0; numpoly < *np; ++numpoly) {
  967.                 fread(&(ply[numpoly].numverts), sizeof(int), 1, f);
  968.                 if(ply[numpoly].numverts <= 0)
  969.                     FATAL_ERROR("Negative primitive size\n");
  970.                 ply[numpoly].index = 
  971.                     (int *)malloc(ply[numpoly].numverts * sizeof(int));
  972.                 fread(ply[numpoly].index, sizeof(int), ply[numpoly].numverts, f);
  973.             }
  974.  
  975.             nRead = fread(&numverts, sizeof(int), 1, f);
  976.             if(nRead != 1) FATAL_ERROR("Unexpected end of input\n");
  977.             if(numverts <= 0) FATAL_ERROR("Negative number of vertexes\n");
  978.             vert = pevent->rb->vert = 
  979.                 (struct vector *)malloc(numverts*sizeof(struct vector));
  980.             vnorm = pevent->rb->vnorm =
  981.                 (struct vector *)malloc(numverts*sizeof(struct vector));
  982.             vcolor = pevent->rb->vcolor = 
  983.                 (struct colorvector *)malloc(numverts*sizeof(struct colorvector));
  984.  
  985.             fread(vert, sizeof(struct vector), numverts, f);
  986.             fread(vnorm, sizeof(struct vector), numverts, f);
  987.             for(i=0; i < numverts; i++) {
  988.                 if(vert[i].x > max[0])
  989.                     max[0] = vert[i].x;
  990.                 else if (vert[i].x < min[0])
  991.                     min[0] = vert[i].x;
  992.  
  993.                 if(vert[i].y > max[1])
  994.                     max[1] = vert[i].y;
  995.                 else if (vert[i].x < min[1])
  996.                     min[1] = vert[i].y;
  997.  
  998.                 if(vert[i].z > max[2])
  999.                     max[0] = vert[i].z;
  1000.                 else if (vert[i].z < min[2])
  1001.                     min[2] = vert[i].z;
  1002.             }
  1003.  
  1004.             compute_bounds(center, trans, min, max);
  1005.             get_colors_ply(vert, vcolor, numverts, trans, objnameptr);
  1006.             break;
  1007.  
  1008.         default:
  1009.             printf("Unrecognized binary version %u", binary_version);
  1010.             exit(1);
  1011.             break;
  1012.         }
  1013.     } else {
  1014.         /* Open .coo file - vertex info */
  1015.         filenameptr = strcpy(filenameptr, objnameptr);
  1016.         filenameptr = strcat(filenameptr, extension[0]);
  1017.  
  1018.         if ((f = fopen(filename, "r")) == 0) {
  1019.             FATAL_ERROR("Couldn't open (coo) input file\n");
  1020.         }
  1021.  
  1022.         /* Read once to get a count */
  1023.         numverts = 0;
  1024.         while ((nRead = fscanf(f, "%d", &index)) == 1) {
  1025.             nRead = fscanf(f, ",%f,%f,%f", &dummy[0], &dummy[1], &dummy[2]);
  1026.             if (nRead == EOF) {
  1027.                 FATAL_ERROR("unexpected end of input\n");
  1028.             }
  1029.             if (nRead != 3) {
  1030.                 FATAL_ERROR("read error getting polygon input\n");
  1031.             }
  1032.             numverts++;
  1033.         }
  1034.         if (nRead != EOF) {
  1035.             FATAL_ERROR("read error getting polygon input\n");
  1036.         }
  1037.         fclose(f);
  1038.         pevent->rb->numverts = numverts;
  1039.  
  1040.         if ((f = fopen(filename, "r")) == 0) {
  1041.             FATAL_ERROR("Couldn't open (coo) input file\n");
  1042.         }
  1043.  
  1044.  
  1045.         /* malloc space and fill it in */
  1046.         vert = pevent->rb->vert = 
  1047.             (struct vector *)malloc((numverts+1)*sizeof(struct vector ));
  1048.  
  1049.         for (i = 1; i <= numverts; i++) {
  1050.             fscanf(f, "%d", &index);
  1051.             fscanf(f, ",%f,%f,%f", &(vert[index].x), &(vert[index].y), 
  1052.                 &(vert[index].z));
  1053.  
  1054.             if (vert[index].x > max[0])
  1055.                 max[0] = vert[index].x;
  1056.             else if (vert[index].x < min[0])
  1057.                 min[0] = vert[index].x;
  1058.  
  1059.             if (vert[index].y > max[1])
  1060.                 max[1] = vert[index].y;
  1061.             else if (vert[index].y < min[1])
  1062.                 min[1] = vert[index].y;
  1063.  
  1064.             if (vert[index].z > max[2])
  1065.                 max[2] = vert[index].z;
  1066.             else if (vert[index].z < min[2])
  1067.                 min[2] = vert[index].z;
  1068.         }
  1069.  
  1070.         /* Open .ele file - connectivity info */
  1071.  
  1072.         fclose(f);
  1073.  
  1074.         filenameptr = strcpy(filenameptr, objnameptr);
  1075.         filenameptr = strcat(filenameptr, extension[1]);
  1076.  
  1077.         if ((f = fopen(filename, "r")) == 0) {
  1078.             FATAL_ERROR("Couldn't open (ele) input file\n");
  1079.         }
  1080.  
  1081.         /* Read once to get a count */
  1082.  
  1083.         while ((nRead = fscanf(f, "%s ", name)) == 1) {
  1084.             i = 0;
  1085.             while ((nRead = fscanf(f, "%d ", &tempspace[i])) == 1)
  1086.                 i++;
  1087.  
  1088.             if (i > 0) { 
  1089.                 (*np)++; 
  1090.             }
  1091.         }
  1092.         if (nRead != EOF) {
  1093.             FATAL_ERROR("read error getting polygon input\n");
  1094.         }
  1095.  
  1096.         fclose(f);
  1097.  
  1098.         /* malloc space and fill it in */
  1099.         ply = pevent->rb->ply = 
  1100.             (struct plygon *)malloc((*np) * sizeof(struct plygon ));
  1101.  
  1102.         if ((f = fopen(filename, "r")) == 0) {
  1103.             FATAL_ERROR("Couldn't open (ele) input file\n");
  1104.         }
  1105.  
  1106.         for (numpoly = 0; numpoly < *np; ++numpoly) {
  1107.             fscanf(f, "%s ", name);
  1108.             i = 0;
  1109.             while ((nRead = fscanf(f, "%d ", &tempspace[i])) == 1)
  1110.                 i++;
  1111.  
  1112.             if (i > 0) {
  1113.                 ply[numpoly].numverts = i;
  1114.                 ply[numpoly].index = (int *) malloc(i * sizeof(int));
  1115.                 for (i = 0; i < ply[numpoly].numverts; i++)
  1116.                     ply[numpoly].index[i] = (int) tempspace[i];
  1117.             }
  1118.         }
  1119.         fclose(f);
  1120.  
  1121.         /* Open .vnm file - vertex normals */
  1122.  
  1123.         filenameptr = strcpy(filenameptr, objnameptr);
  1124.         filenameptr = strcat(filenameptr, extension[2]);
  1125.  
  1126.         /* already have count so malloc space and fill it in */
  1127.  
  1128.         vnorm = pevent->rb->vnorm = 
  1129.             (struct vector *)malloc((numverts + 1) * sizeof(struct vector ));
  1130.  
  1131.         if ((f = fopen(filename, "r")) == 0) {
  1132.             FATAL_ERROR("Couldn't open (vnm) input file\n");
  1133.         }
  1134.         for (i = 1; i <= numverts; i++)
  1135.             nRead = fscanf(f, "%f %f %f\n", &vnorm[i].x, &vnorm[i].y, &vnorm[i].z);
  1136.         if (nRead != 3) {
  1137.             FATAL_ERROR("read error in .vnm file\n");
  1138.         }
  1139.         fclose(f);
  1140.  
  1141.  
  1142.         /* Compute bounding box info */
  1143.         compute_bounds(center, trans, min, max);
  1144.  
  1145.         /* compute vertex color and fill them in */
  1146.         vcolor = pevent->rb->vcolor = 
  1147.             (struct colorvector *)malloc((numverts+1)*sizeof(struct colorvector ));
  1148.  
  1149.         get_colors_ply(vert, vcolor, numverts, trans, objnameptr);
  1150.     }
  1151.     /* count the number of vertex calls per frame */
  1152.  
  1153.     vertsperframe = 0;
  1154.     for (i = 0; i < *np; i++) {
  1155.         vertsperframe += ply[i].numverts;
  1156.     }
  1157. }
  1158.  
  1159.  
  1160. void get_colors_ply(struct vector *vert, struct colorvector *vcolor, 
  1161. int numverts, GLfloat *trans, char *objnameptr)
  1162. {
  1163.     int colorflag;
  1164.     GLfloat maxmag = SMALL;
  1165.     GLfloat minmag = BIG;
  1166.     int i;
  1167.     FILE * f;
  1168.     char filename[512], *filenameptr;
  1169.  
  1170.     filenameptr = filename;
  1171.     filenameptr = strcpy(filenameptr, objnameptr);
  1172.     filenameptr = strcat(filenameptr, extension[3]);
  1173.  
  1174.     if((f = fopen(filename, BINARY_FILE)) == 0) {
  1175.         colorflag = 0;
  1176.     } else {
  1177.         colorflag = 1;
  1178.     }
  1179.  
  1180.     if (!colorflag) {
  1181.         for (i = 1; i <= numverts; i++) {
  1182.             compare_min_max(&(vert[i]), trans, &minmag, &maxmag);
  1183.         }
  1184.     }
  1185.  
  1186.     for (i = 1; i <= numverts; i++) {
  1187.         if(colorflag) {
  1188.             read_colors(&(vcolor[i]), f);
  1189.         } else {
  1190.             calculate_colors(&(vcolor[i]), &(vert[i]), trans, maxmag, minmag);
  1191.         }
  1192.     }
  1193.     if(colorflag)
  1194.         fclose(f);
  1195. }
  1196.  
  1197. GLfloat MinAngle( GLfloat from, GLfloat to)
  1198. {
  1199.     GLfloat delta = to - from;
  1200.     if (fabs(delta) > 180.) {
  1201.     return (from > to) ? delta + 360. : delta - 360.;
  1202.     } else {
  1203.     return delta;
  1204.     }
  1205. }
  1206.  
  1207. void    walkthruinput(char *objnameptr, struct EventBlock *pevent)
  1208. {
  1209.     FILE *fp;
  1210.     char filename[512], *filenameptr;
  1211.     GLfloat eyeX, eyeY, eyeZ;
  1212.     GLfloat p_eyeX, p_eyeY, p_eyeZ;
  1213.     GLfloat heading, p_heading;
  1214.     GLfloat pitch, p_pitch;
  1215.     GLfloat roll, p_roll;
  1216.     int frame;
  1217.     int p_frame;
  1218.     int f;
  1219.     const int sizeInc = 10;
  1220.     int size = sizeInc;
  1221.     GLfloat **walkthru = (GLfloat**)malloc(sizeof(GLfloat*)*size);
  1222.     GLfloat dt, dex, dey, dez, dh, dp, dr;
  1223.  
  1224.     filenameptr = filename;
  1225.     filenameptr = strcpy(filenameptr, objnameptr);
  1226.     filenameptr = strcat(filenameptr, extension[6]);
  1227.     if ((fp = fopen(filename, "r"))) {
  1228.         glMatrixMode(GL_MODELVIEW);
  1229.         glPushMatrix();
  1230.         glLoadIdentity();
  1231.         while (fscanf(fp, "%d %f %f %f %f %f %f",
  1232.                   &frame,
  1233.                   &eyeX, &eyeY, &eyeZ,
  1234.                   &heading, &pitch, &roll) !=EOF) {
  1235.             if (frame > 0) {
  1236.                 dt = frame - p_frame;
  1237.                 dex = (eyeX - p_eyeX)/dt;
  1238.                 dey = (eyeY - p_eyeY)/dt;
  1239.                 dez = (eyeZ - p_eyeZ)/dt;
  1240.                 dh = MinAngle(p_heading, heading)/dt;
  1241.                 dp = MinAngle(p_pitch, pitch)/dt;
  1242.                 dr = MinAngle(p_roll, roll)/dt;
  1243.                 for (f = p_frame; f < frame; f++) {
  1244.                     float i = f - p_frame;
  1245.                     glPushMatrix();
  1246.                     glRotatef(-90.0,                 1.0, 0.0, 0.0);
  1247.                     glRotatef(-(p_roll + i * dr),    0.0, 1.0, 0.0);
  1248.                     glRotatef(-(p_pitch + i * dp),   1.0, 0.0, 0.0);
  1249.                     glRotatef(-(p_heading + i * dh), 0.0, 0.0, 1.0);
  1250.                     glTranslatef(
  1251.                         -(p_eyeX + i * dex),
  1252.                         -(p_eyeY + i * dey),
  1253.                         -(p_eyeZ + i * dez)
  1254.                     );
  1255.                     if (f == size) {
  1256.                         size += sizeInc;
  1257.                         walkthru = (GLfloat**)realloc(walkthru, sizeof(GLfloat*)*size);
  1258.                     }
  1259.                     walkthru[f] = (GLfloat*)malloc(sizeof(GLfloat)*16);
  1260.                     glGetFloatv(GL_MODELVIEW_MATRIX, walkthru[f]);
  1261.                     glPopMatrix();
  1262.                 }
  1263.             }
  1264.             p_frame = frame;
  1265.             p_eyeX = eyeX;
  1266.             p_eyeY = eyeY;
  1267.             p_eyeZ = eyeZ;
  1268.             p_heading = heading;
  1269.             p_pitch = pitch;
  1270.             p_roll = roll;
  1271.         }
  1272.         glPopMatrix();
  1273.     if (pevent->numframes == 0) {
  1274.         pevent->numframes = frame;
  1275.     } else if (pevent->numframes > frame) {
  1276.         FATAL_ERROR("viewperf: -numframes greater than defined positions in walkthru file\n");
  1277.     }
  1278.     pevent->walkthru = walkthru;
  1279.     } else {
  1280.         FATAL_ERROR("viewperf: could not find walkthru file\n");
  1281.     }
  1282. }
  1283.  
  1284. /*********************************************************************/
  1285. /*                                                                   */
  1286. /*  triquadinput reads in triangle and quad data sets and computes   */
  1287. /*  vertex data                                                      */
  1288. /*                                                                   */
  1289. /*********************************************************************/
  1290.  
  1291. void    triquadinput(char *objnameptr, int vertsperobj, struct EventBlock *pevent)
  1292. {
  1293.     int    i;
  1294.     FILE * f;
  1295.     int    numverts;
  1296.     int    numpoly;
  1297.     char    filename[512], *filenameptr;
  1298.     int    tempspace[4];
  1299.     GLfloat maxmag, minmag, vertmag;
  1300.     GLfloat tmp;
  1301.     char    name[1024];
  1302.     int    nRead;
  1303.     int    index, colorflag;
  1304.     GLfloat dummy[3];
  1305.     GLfloat * trans = pevent->trans;
  1306.     GLfloat * center = pevent->center;
  1307.     struct vector *vert;
  1308.     struct vector *vnorm;
  1309.     struct colorvector *vcolor;
  1310.     struct plygon *ply;
  1311.     int    *np = &pevent->rb->np;
  1312.     float    max[3], min[3];
  1313.     unsigned binary_version;
  1314.     GLenum datatype;
  1315.  
  1316.     *np = 0;
  1317.  
  1318.     filenameptr = filename;
  1319.  
  1320.     for (i = 0; i < 3; i++) {
  1321.         max[i] = SMALL;
  1322.         min[i] = BIG;
  1323.     }
  1324.  
  1325.  
  1326.     filenameptr = strcpy(filenameptr, objnameptr);
  1327.     filenameptr = strcat(filenameptr, extension[5]);
  1328.     if((f = fopen(filename, BINARY_FILE))) {
  1329.         nRead = fread(&binary_version, sizeof(unsigned int), 1, f);
  1330.         if(nRead == 0) {
  1331.             FATAL_ERROR("Unexpected end of input in binary file\n");
  1332.         }
  1333.         switch(binary_version) {
  1334.         case 0:
  1335.             nRead = fread(&datatype, sizeof(GLenum), 1, f);
  1336.             if(nRead != 1) FATAL_ERROR("Unexpected end of input\n");
  1337.             if(!(((datatype == GL_TRIANGLES) && (vertsperobj == 3)) ||
  1338.                 ((datatype == GL_QUADS)) && (vertsperobj == 4)))
  1339.             {
  1340.                 FATAL_ERROR("primitive type not triangles or quads\n");
  1341.             }
  1342.  
  1343.             fread(&numverts, sizeof(unsigned), 1, f);
  1344.             pevent->rb->numverts = numverts;
  1345.             if(nRead != 1) FATAL_ERROR("Unexpected end of input\n");
  1346.             vert = pevent->rb->vert = 
  1347.                 (struct vector *)malloc((numverts+1)*sizeof(struct vector));
  1348.             fread(&vert[1], sizeof(struct vector), numverts, f);
  1349.  
  1350.             for(i=1; i <= numverts; i++) {
  1351.                 if (vert[i].x > max[0])
  1352.                     max[0] = vert[i].x;
  1353.                 else if (vert[i].x < min[0])
  1354.                     min[0] = vert[i].x;
  1355.  
  1356.                 if (vert[i].y > max[1])
  1357.                     max[1] = vert[i].y;
  1358.                 else if (vert[i].y < min[1])
  1359.                     min[1] = vert[i].y;
  1360.  
  1361.                 if (vert[i].z > max[2])
  1362.                     max[2] = vert[i].z;
  1363.                 else if (vert[i].z < min[2])
  1364.                     min[2] = vert[i].z;
  1365.             }
  1366.  
  1367.             *np = numverts / vertsperobj;
  1368.             vnorm = pevent->rb->vnorm = 
  1369.                 (struct vector *)malloc(numverts*sizeof(struct vector));
  1370.             fread(vert, sizeof(struct vector), numverts, f);
  1371.             ply = pevent->rb->ply = 
  1372.                 (struct plygon *)malloc((*np) * sizeof(struct plygon ));
  1373.             for(numpoly = 0; numpoly < *np; ++numpoly) {
  1374.                 ply[numpoly].numverts = vertsperobj;
  1375.                 ply[numpoly].index = (int *)malloc(vertsperobj *sizeof(int));
  1376.                 fread(ply[numpoly].index, sizeof(int), vertsperobj, f);
  1377.             }
  1378.  
  1379.  
  1380.             compute_bounds(center, trans, min, max);
  1381.             vcolor = pevent->rb->vcolor = 
  1382.                 (struct colorvector*)malloc((numverts)*sizeof(struct colorvector));
  1383.             get_colors_triquad(vert, vcolor, numverts, trans, objnameptr);
  1384.             fclose(f);
  1385.             break;
  1386.         default:
  1387.             printf("Unrecognized binary version %u", binary_version);
  1388.             exit(1);
  1389.             break;
  1390.         }
  1391.     } else {
  1392.         /* Open .coo file - vertex info */
  1393.         filenameptr = strcpy(filenameptr, objnameptr);
  1394.         filenameptr = strcat(filenameptr, extension[0]);
  1395.  
  1396.         if ((f = fopen(filename, "r")) == 0) {
  1397.             FATAL_ERROR("Couldn't open (coo) input file\n");
  1398.         }
  1399.  
  1400.         /* Read once to get a count */
  1401.  
  1402.         numverts = 0;
  1403.         while ((nRead = fscanf(f, "%d", &index)) == 1) {
  1404.             nRead = fscanf(f, ",%f,%f,%f", &dummy[0], &dummy[1], &dummy[2]);
  1405.             if (nRead == EOF) {
  1406.                 FATAL_ERROR("unexpected end of input\n");
  1407.             }
  1408.             if (nRead != 3) {
  1409.                 FATAL_ERROR("read error in .coo file\n");
  1410.             }
  1411.             numverts++;
  1412.         }
  1413.         if (nRead != EOF) {
  1414.             FATAL_ERROR("read error in .coo file (2)\n");
  1415.         }
  1416.         fclose(f);
  1417.  
  1418.         /* malloc space and fill it in */
  1419.  
  1420.         vert = pevent->rb->vert = 
  1421.             (struct vector *)malloc((numverts + 1) * sizeof(struct vector ));
  1422.         pevent->rb->numverts = numverts;
  1423.  
  1424.         if ((f = fopen(filename, "r")) == 0) {
  1425.             FATAL_ERROR("Couldn't open (coo) input file\n");
  1426.         }
  1427.         for (i = 1; i <= numverts; i++) {
  1428.             fscanf(f, "%d", &index);
  1429.             fscanf(f, ",%f,%f,%f", 
  1430.                 &(vert[index].x), &(vert[index].y), &(vert[index].z));
  1431.  
  1432.             if (vert[i].x > max[0])
  1433.                 max[0] = vert[i].x;
  1434.             else if (vert[i].x < min[0])
  1435.                 min[0] = vert[i].x;
  1436.  
  1437.             if (vert[i].y > max[1])
  1438.                 max[1] = vert[i].y;
  1439.             else if (vert[i].y < min[1])
  1440.                 min[1] = vert[i].y;
  1441.  
  1442.             if (vert[i].z > max[2])
  1443.                 max[2] = vert[i].z;
  1444.             else if (vert[i].z < min[2])
  1445.                 min[2] = vert[i].z;
  1446.         }
  1447.  
  1448.         fclose(f);
  1449.  
  1450.         /* Open .ele file - connectivity info */
  1451.         filenameptr = strcpy(filenameptr, objnameptr);
  1452.         filenameptr = strcat(filenameptr, extension[1]);
  1453.  
  1454.         if ((f = fopen(filename, "r")) == 0) {
  1455.             FATAL_ERROR("Couldn't open (ele) input file\n");
  1456.         }
  1457.  
  1458.         while ((nRead = fscanf(f, "%s ", name)) == 1) {
  1459.  
  1460.             i = 0;
  1461.             while ((nRead = fscanf(f, "%d ", &tempspace[i])) == 1)
  1462.                 i++;
  1463.             if (i != vertsperobj) {
  1464.                 FATAL_ERROR("Input file doesn't match input type\n");
  1465.             }
  1466.  
  1467.             if (i > 0) {
  1468.                 (*np)++;
  1469.             }
  1470.         }
  1471.         if (nRead != EOF) {
  1472.             FATAL_ERROR("read error in .ele file\n");
  1473.         }
  1474.  
  1475.         fclose(f);
  1476.  
  1477.         /* malloc space and fill it in */
  1478.  
  1479.         ply = pevent->rb->ply = 
  1480.             (struct plygon *)malloc((*np) * sizeof(struct plygon ));
  1481.  
  1482.         if ((f = fopen(filename, "r")) == 0) {
  1483.             FATAL_ERROR("Couldn't open (ele) input file\n");
  1484.         }
  1485.  
  1486.         for (numpoly = 0; numpoly < *np; ++numpoly) {
  1487.             fscanf(f, "%s ", name);
  1488.             ply[numpoly].numverts = vertsperobj;
  1489.             ply[numpoly].index = (int *) malloc(vertsperobj * sizeof(int));
  1490.             for (i = 0; i < ply[numpoly].numverts; i++)
  1491.                 fscanf(f, "%d ", &ply[numpoly].index[i]);
  1492.         }
  1493.         fclose(f);
  1494.  
  1495.         /* Open .vnm file - vertex normal info */
  1496.  
  1497.         filenameptr = strcpy(filenameptr, objnameptr);
  1498.         filenameptr = strcat(filenameptr, extension[2]);
  1499.  
  1500.         /* already know how many so malloc and fill in */
  1501.  
  1502.         vnorm = pevent->rb->vnorm = 
  1503.             (struct vector *)malloc((numverts + 1) * sizeof(struct vector ));
  1504.  
  1505.         if ((f = fopen(filename, "r")) == 0) {
  1506.             FATAL_ERROR("Couldn't open (vnm) input file\n");
  1507.         }
  1508.         for (i = 1; i <= numverts; i++)
  1509.             nRead = fscanf(f, "%f %f %f\n", &vnorm[i].x, &vnorm[i].y, &vnorm[i].z);
  1510.         if (nRead != 3) {
  1511.             FATAL_ERROR("read error in .vnm file\n");
  1512.         }
  1513.         fclose(f);
  1514.  
  1515.  
  1516.         /* Compute bounding box info */
  1517.         compute_bounds(center, trans, min, max);
  1518.  
  1519.         /* Compute vertex color, malloc space, and fill it in */
  1520.         vcolor = pevent->rb->vcolor = 
  1521.             (struct colorvector *)malloc((numverts+1)*sizeof(struct colorvector));
  1522.  
  1523.         get_colors_triquad(vert, vcolor, numverts, trans, objnameptr);
  1524.     }
  1525.  
  1526.     /* Count the number of vertex calls per frame */
  1527.  
  1528.     vertsperframe = 0;
  1529.     for (i = 0; i < *np; i++) {
  1530.         vertsperframe += ply[i].numverts;
  1531.     }
  1532. }
  1533.  
  1534. void get_colors_triquad(struct vector *vert, struct colorvector *vcolor, 
  1535. int numverts, GLfloat *trans, char *objnameptr)
  1536. {
  1537.     int colorflag;
  1538.     GLfloat maxmag = SMALL;
  1539.     GLfloat minmag = BIG;
  1540.     int i;
  1541.     FILE *f;
  1542.     char filename[512], *filenameptr;
  1543.  
  1544.     filenameptr = filename;
  1545.     filenameptr = strcpy(filenameptr, objnameptr);
  1546.     filenameptr = strcat(filenameptr, extension[3]);
  1547.  
  1548.     if((f = fopen(filename, BINARY_FILE)) == 0) {
  1549.         colorflag = 0;
  1550.     }
  1551.     else
  1552.         colorflag = 1;
  1553.  
  1554.     if(!colorflag) {
  1555.         for (i = 1; i <= numverts; i++) {
  1556.             compare_min_max(&vert[i], trans, &minmag, &maxmag);
  1557.         }
  1558.     }
  1559.  
  1560.  
  1561.     if(colorflag) {
  1562.         for (i = 1; i <= numverts; i++) {
  1563.             read_colors(&vcolor[i], f);
  1564.         }
  1565.     } else {
  1566.         for (i = 1; i <= numverts; i++) {
  1567.             calculate_colors(&vcolor[i], &vert[i], trans, maxmag, minmag);
  1568.         }
  1569.     }
  1570.  
  1571.     if(colorflag)
  1572.         fclose(f);
  1573. }
  1574.  
  1575. /*********************************************************************/
  1576. /*                                                                   */
  1577. /*  Define all material, lighting and lighting model parameters      */
  1578. /*                                                                   */
  1579. /*********************************************************************/
  1580.  
  1581. void SetLightingState(int infiniteLights, int localLights, GLfloat localViewer, GLenum twoSidedLighting, int cmenable, int cmface, int cmmode, int blendOn)
  1582. {
  1583.     int i;
  1584.     GLfloat normFactor;
  1585.  
  1586.     /* Material settings */
  1587.     GLfloat materialAmbientColor[4] = {
  1588.         0.5F, 0.5F, 0.5F, 1.0F
  1589.     };
  1590.  
  1591.     GLfloat materialDiffuseColor[4] = {
  1592.         0.7F, 0.7F, 0.7F, 1.0F
  1593.     };
  1594.  
  1595.     GLfloat materialSpecularColor[4] = {
  1596.         1.0F, 1.0F, 1.0F, 1.0F
  1597.     };
  1598.  
  1599.     GLfloat materialShininess[1] = {
  1600.         128
  1601.     };
  1602.  
  1603.     /* Lighting settings */
  1604.     GLfloat lightPosition[8][4] = {
  1605.         {  1.0F,  1.0F,  1.0F, 1.0F },
  1606.         {  1.0F,  0.0F,  1.0F, 1.0F },
  1607.         {  1.0F, -1.0F,  1.0F, 1.0F },
  1608.         {  0.0F, -1.0F,  1.0F, 1.0F },
  1609.         { -1.0F, -1.0F,  1.0F, 1.0F },
  1610.         { -1.0F,  0.0F,  1.0F, 1.0F },
  1611.         { -1.0F,  1.0F,  1.0F, 1.0F },
  1612.         {  0.0F,  1.0F,  1.0F, 1.0F }
  1613.     };
  1614.  
  1615.     GLfloat lightDiffuseColor[8][4] = {
  1616.         { 1.0F, 1.0F, 1.0F, 1.0F },
  1617.         { 0.0F, 1.0F, 1.0F, 1.0F },
  1618.         { 1.0F, 0.0F, 1.0F, 1.0F },
  1619.         { 1.0F, 1.0F, 0.0F, 1.0F },
  1620.         { 1.0F, 0.0F, 0.0F, 1.0F },
  1621.         { 0.0F, 1.0F, 0.0F, 1.0F },
  1622.         { 0.0F, 0.0F, 1.0F, 1.0F },
  1623.         { 1.0F, 1.0F, 1.0F, 1.0F }
  1624.     };
  1625.  
  1626.     GLfloat lightAmbientColor[4] = {
  1627.         0.1F, 0.1F, 0.1F, 1.0F
  1628.     };
  1629.  
  1630.     GLfloat lightSpecularColor[4] = {
  1631.         1.0F, 1.0F, 1.0F, 1.0F
  1632.     };
  1633.  
  1634.     GLfloat lightModelAmbient[4] = {
  1635.         0.5F, 0.5F, 0.5F, 1.0F
  1636.     };
  1637.  
  1638.     GLfloat alpha = blendOn ? 0.5F : 1.0F;
  1639.  
  1640.     if (infiniteLights + localLights == 0)
  1641.         return;
  1642.  
  1643.     normFactor = 1.0F / (GLfloat)(infiniteLights + localLights);
  1644.  
  1645.     materialDiffuseColor[3] = alpha;
  1646.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, materialDiffuseColor);
  1647.     materialAmbientColor[3] = alpha;
  1648.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, materialAmbientColor);
  1649.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecularColor);
  1650.     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, materialShininess);
  1651.  
  1652.     lightAmbientColor[0] *= normFactor;
  1653.     lightAmbientColor[1] *= normFactor;
  1654.     lightAmbientColor[2] *= normFactor;
  1655.  
  1656.     for (i = 0; i < localLights + infiniteLights; i++) {
  1657.         lightPosition[i][3] = (GLfloat)(i < localLights);
  1658.         lightDiffuseColor[i][0] *= normFactor;
  1659.         lightDiffuseColor[i][1] *= normFactor;
  1660.         lightDiffuseColor[i][2] *= normFactor;
  1661.         glLightfv(GL_LIGHT0 + i, GL_POSITION, lightPosition[i]);
  1662.         glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  lightDiffuseColor[i]);
  1663.         glLightfv(GL_LIGHT0 + i, GL_AMBIENT,  lightAmbientColor);
  1664.         glLightfv(GL_LIGHT0 + i, GL_SPECULAR, lightSpecularColor);
  1665.         glEnable(GL_LIGHT0 + i);
  1666.     }
  1667.  
  1668.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lightModelAmbient);
  1669.     glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, localViewer);
  1670.     glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, twoSidedLighting);
  1671.  
  1672.     if (cmenable) {
  1673.         glColorMaterial(cmface, cmmode);
  1674.         glEnable(GL_COLOR_MATERIAL);
  1675.     }
  1676.  
  1677.     glEnable(GL_LIGHTING);
  1678. }
  1679.  
  1680.  
  1681. /*********************************************************************/
  1682. /*                                                                   */
  1683. /*  Stroke out cute little text for the title screen                 */
  1684. /*                                                                   */
  1685. /*********************************************************************/
  1686.  
  1687. DrawString(char *str, GLfloat x, GLfloat y)
  1688. {
  1689.     short    nseg, nstroke;
  1690.     short    *cptr;
  1691.     int    i, j;
  1692.  
  1693.     glPushMatrix();
  1694.     glTranslatef (x, y, 0.0F);
  1695.     glScalef (10.0F, 10.0F, 1.0F);
  1696.  
  1697.  
  1698.     while (*str) {
  1699.         cptr = &(chrtbl[*str][0]);
  1700.         nseg = *(cptr++);
  1701.         for (i = 0; i < nseg; i++) {
  1702.             nstroke = *(cptr++);
  1703.             glBegin(GL_LINE_STRIP);
  1704.             for (j = 0; j < nstroke; j++) {
  1705.                 glVertex2sv(cptr);
  1706.                 cptr += 2;
  1707.             }
  1708.             glEnd();
  1709.         }
  1710.         glTranslatef (6.0F, 0.0F, 0.0F);
  1711.         str++;
  1712.     }
  1713.     glPopMatrix();
  1714. }
  1715.  
  1716.  
  1717. /*********************************************************************/
  1718. /*                                                                   */
  1719. /*  rmnoop is plugged into the jump tables where ever there are      */
  1720. /*  holes.  They should never be called if everything is working     */
  1721. /*  as planned .. but just in case we'll print an error message.     */
  1722. /*                                                                   */
  1723. /*********************************************************************/
  1724.  
  1725. void    rmnoop(struct ThreadBlock *tb)
  1726. {
  1727.     fprintf(stderr, "This RenderMode is not available for the selected data set\n");
  1728. }
  1729.  
  1730.  
  1731. /*********************************************************************/
  1732. /*                                                                   */
  1733. /*  Extern routines are plugged into renderers that turn on and off  */
  1734. /*  OpenGL capabilities. These are called once per primitive         */
  1735. /*  through a function pointer. Special "Extern" render routines     */
  1736. /*  have been created that call these functions as part of their     */
  1737. /*  rendering duties. Look in VP_OBJS for their names.               */
  1738. /*                                                                   */
  1739. /*********************************************************************/
  1740.  
  1741. void    toggle_capability(GLenum capability)
  1742. {
  1743.     static int    toggleon = 0;
  1744.  
  1745.     if (toggleon = 1 - toggleon)
  1746.         glEnable(capability);
  1747.     else
  1748.         glDisable(capability);
  1749. }
  1750.  
  1751.  
  1752. void    toggle_linewidth(GLenum dummy)
  1753. {
  1754.     static GLfloat togglewide = 0.0F;
  1755.  
  1756.     togglewide = 1.0F - togglewide;
  1757.     glLineWidth(togglewide + 1.0F);
  1758. }
  1759.  
  1760.  
  1761. void    toggle_matrix(GLenum dummy)
  1762. {
  1763.     static GLfloat matrix[] = {
  1764.         1.0F, 0.0F, 0.0F, 0.0F,
  1765.         0.0F, 1.0F, 0.0F, 0.0F,
  1766.         0.0F, 0.0F, 1.0F, 0.0F,
  1767.         0.0F, 0.0F, 0.0F, 1.0F             };
  1768.  
  1769.     glMultMatrixf(matrix);
  1770. }
  1771.  
  1772.  
  1773. /*********************************************************************/
  1774. /*********************************************************************/
  1775. /*********************************************************************/
  1776. /*********************************************************************/
  1777. /*                                                                   */
  1778. /*  Mr. Main                                                         */
  1779. /*                                                                   */
  1780. /*********************************************************************/
  1781. /*********************************************************************/
  1782. /*********************************************************************/
  1783. /*********************************************************************/
  1784.  
  1785. main(int argc, char *argv[])
  1786. {
  1787.     char *ptr;
  1788.     char tempstring[512];
  1789.     GLenum vistype = 0;
  1790.     int    i, j, k;
  1791.     int    thread;
  1792.  
  1793.     FILE * f, *texfile;
  1794.  
  1795.     int    numInfiniteLights = 0;
  1796.     int    numLocalLights = 0;
  1797.     GLenum lighttwoside = GL_FALSE;
  1798.  
  1799.     int    vis_id = 0;
  1800.     GLenum vis_criteria = AUX_MINIMUM_CRITERIA;
  1801.  
  1802.     int    renderDoubleBuffer = VP_TRUE;
  1803.     int    colormode = COLOR_PER_FRAME;
  1804.     int    inputmode = NOINPUT;
  1805.     int    batchmode = VP_FALSE;
  1806.     int    numtobatch = 0;
  1807.     int    facetnormalmode = VP_FALSE;
  1808.     int    linesmoothmode = VP_FALSE;
  1809.     int    polysmoothmode = VP_FALSE;
  1810.     int    backfacemode = VP_FALSE;
  1811.     int    frontfacemode = VP_FALSE;
  1812.     int    zbuffermode = VP_FALSE;
  1813.     int    fogmode = VP_FALSE;
  1814.     int    clipmode = VP_FALSE;
  1815.     GLenum shademodelmode = GL_SMOOTH;
  1816.     int    polystipplemode = VP_FALSE;
  1817.     int    linestipplemode = VP_FALSE;
  1818.     int    togglemode = VP_FALSE;
  1819.     int    togglelinewidthmode = VP_FALSE;
  1820.     int    togglematrixmode = VP_FALSE;
  1821.     int    orthomode = VP_FALSE;
  1822.     int    dithermode = VP_TRUE;
  1823.     int    texturemode = VP_FALSE;
  1824.     int    texgenmode = TXG_NO_TEX_GEN;
  1825.     GLenum texenvmode = GL_DECAL;
  1826.     int    blendmode = VP_FALSE;
  1827.     GLenum sblendfunc = GL_SRC_ALPHA;
  1828.     GLenum dblendfunc = GL_ONE_MINUS_SRC_ALPHA;
  1829.     int    rendermode = LINEmode;
  1830.     int    displaylistmode = VP_FALSE;
  1831.     GLfloat linewidthmode = 1.0F;
  1832.     GLfloat localviewmode = 0.0F;
  1833.     GLenum polymodefront = GL_FILL;
  1834.     GLenum polymodeback = GL_FILL;
  1835.     int     mblurmode = VP_FALSE;
  1836.     GLfloat blur_amount = 0.0;
  1837.     int     fsantimode = VP_FALSE;
  1838.     int     fsaredraw = 0;
  1839.     GLfloat fsajitter = 0.0F;
  1840.     struct vector *jitter;
  1841.     int     walkthrumode = VP_FALSE;
  1842.     int     cmface = GL_FRONT;
  1843.     int     cmmode = GL_AMBIENT_AND_DIFFUSE;
  1844.     int     cmenable = VP_FALSE;
  1845.  
  1846.     char    filename[512], *filenameptr;
  1847.     char    objname[64], *objnameptr;
  1848.  
  1849.     char    header[64];
  1850.     char    *depth;
  1851.     long    pack;
  1852.     int    row, col, index;
  1853.     int    xpix, ypix;
  1854.     int    numpix;
  1855.     int    numcomp = 3;
  1856.     GLfloat minfilter = GL_NEAREST;
  1857.     GLfloat magfilter = GL_NEAREST;
  1858.     unsigned char    *Image;
  1859.     unsigned char    *TextureImage;
  1860.  
  1861.     RenderIndex rfindex;
  1862.     EventLoopIndex elindex;
  1863.     struct RenderBlock renderblock;
  1864.     struct ThreadBlock *tb;
  1865.  
  1866.     GLfloat * trans = eventblock.trans;
  1867.     GLfloat * center = eventblock.center;
  1868.  
  1869.     EnvironmentInfo environ;
  1870.     char *leader = OUTPUT_LEADER;
  1871.     int nameWidth = OUTPUT_NAME_WIDTH;
  1872.  
  1873.     environ.directRender = VP_TRUE;
  1874.     environ.bufConfig.doubleBuffer = VP_TRUE;
  1875.     environ.windowWidth = X_WINDOW_SIZE;
  1876.     environ.windowHeight = Y_WINDOW_SIZE;
  1877.  
  1878.     eventblock.rb = &renderblock;
  1879.     eventblock.numframes = 0;
  1880.     eventblock.minperiod = MIN_TEST_TIME;
  1881.     eventblock.threads = 1;
  1882.  
  1883.     filenameptr = filename;
  1884.     objnameptr = objname;
  1885.  
  1886.  
  1887.  
  1888. #ifdef WIN32
  1889.     LogFile = fopen("viewperf.log", "a");
  1890. #endif
  1891.  
  1892.     /* Save a copy of the command line arguments */
  1893.     strcpy( cmdln , "\0" );
  1894.     for( i=1 ; i< argc ; i++) {
  1895.         strcat(cmdln,argv[i]);
  1896.         strcat(cmdln," ");
  1897.     }
  1898.  
  1899.     /*********************************************************************/
  1900.     /*                                                                   */
  1901.     /*  Get your branch units ready ...                                  */
  1902.     /*  Parse the command line args and set viewperf mode variables      */
  1903.     /*                                                                   */
  1904.     /*********************************************************************/
  1905.  
  1906.     while (--argc) {
  1907.         ++argv;
  1908.  
  1909.         /*** Options accepting arguments. ***/
  1910.         if (strcmp ("-backface", argv[0]) == 0 || 
  1911.             strcmp ("-bf", argv[0]) == 0) {
  1912.             backfacemode = VP_TRUE;
  1913.         } else if (strcmp ("-frontface", argv[0]) == 0 || 
  1914.             strcmp ("-ff", argv[0]) == 0)
  1915.         {
  1916.             frontfacemode = VP_TRUE;
  1917.         } else if (strcmp ("-mblur", argv[0]) == 0) {
  1918.             if(argc == 1)
  1919.                 FATAL_ERROR ("viewperf: the -mblur flag requires a number of frames.\n");
  1920.             mblurmode = VP_TRUE;
  1921.             blur_amount =  atof(argv[1]);
  1922.             vistype |= AUX_ACCUM;
  1923.             ARG_INC;
  1924.         } else if (strcmp("-aa_multi", argv[0]) == 0) {
  1925.             if(argc < 3)
  1926.                 FATAL_ERROR ("viewperf: the -aa_multi flag requires # of samples and jitter distance.\n");
  1927.             fsantimode = VP_TRUE;
  1928.             fsaredraw = atoi(argv[1]);
  1929.             fsajitter = atof(argv[2]);
  1930.             jitter = (struct vector *)malloc((fsaredraw +1)* sizeof(struct vector));
  1931.             jitter[0].x = 0;
  1932.             jitter[0].y = 0;
  1933.             jitter[0].z = 0;
  1934.             for(i=1; i<= fsaredraw; i++)
  1935.             {
  1936.                 jitter[i].x = fsajitter * cos(2.0*PI*i/fsaredraw);
  1937.                 jitter[i].y = fsajitter * sin(2.0*PI*i/fsaredraw);
  1938.             }
  1939.             vistype |= AUX_ACCUM;
  1940.             ARG_INC;
  1941.             ARG_INC;
  1942.         } else if (strcmp ("-rendermode", argv[0]) == 0 || 
  1943.             strcmp ("-rm", argv[0]) == 0) {
  1944.             if (argc == 1)
  1945.                 FATAL_ERROR ("viewperf: the -rendermode flag requires an argument.\n");
  1946.             if (strcmp ("VECTOR", argv[1]) == 0)
  1947.                 rendermode = VECTORmode;
  1948.             else if (strcmp ("LINE", argv[1]) == 0)
  1949.                 rendermode = LINEmode;
  1950.             else if (strcmp ("POLYGON", argv[1]) == 0)
  1951.                 rendermode = POLYGONmode;
  1952.             else if (strcmp ("TFAN", argv[1]) == 0)
  1953.                 rendermode = TFANmode;
  1954.             else if (strcmp ("POINT", argv[1]) == 0)
  1955.                 rendermode = POINTmode;
  1956.             else if (strcmp ("TMESH", argv[1]) == 0)
  1957.                 rendermode = TMESHmode;
  1958.             else if (strcmp ("TRIANGLE", argv[1]) == 0)
  1959.                 rendermode = TRImode;
  1960.             else if (strcmp ("QUAD", argv[1]) == 0)
  1961.                 rendermode = QUADmode;
  1962.             ARG_INC;
  1963.         } else if (strcmp ("-linesmooth", argv[0]) == 0 || 
  1964.             strcmp ("-ls", argv[0]) == 0) {
  1965.             linesmoothmode = VP_TRUE;
  1966.         } else if (strcmp ("-facetnormal", argv[0]) == 0 || 
  1967.             strcmp ("-fn", argv[0]) == 0) {
  1968.             facetnormalmode = VP_TRUE;
  1969.         } else if (strcmp ("-displaylist", argv[0]) == 0 || 
  1970.             strcmp ("-dl", argv[0]) == 0) {
  1971.             displaylistmode = VP_TRUE;
  1972.         } else if (strcmp ("-flat", argv[0]) == 0 || 
  1973.             strcmp ("-f", argv[0]) == 0) {
  1974.             shademodelmode = GL_FLAT;
  1975.         } else if (strcmp ("-indirectrender", argv[0]) == 0 || 
  1976.             strcmp ("-ir", argv[0]) == 0) {
  1977.             environ.directRender = VP_FALSE;
  1978.         } else if (strcmp ("-vaccum", argv[0]) == 0 || 
  1979.             strcmp ("-vac", argv[0]) == 0) {
  1980.             vistype |= AUX_ACCUM;
  1981.         } else if (strcmp ("-valpha", argv[0]) == 0 || 
  1982.             strcmp ("-val", argv[0]) == 0) {
  1983.             vistype |= AUX_ALPHA;
  1984.         } else if (strcmp ("-vdepthbuffer", argv[0]) == 0 || 
  1985.             strcmp ("-vz", argv[0]) == 0) {
  1986.             vistype |= AUX_DEPTH;
  1987.         } else if (strcmp ("-vstencil", argv[0]) == 0 || 
  1988.             strcmp ("-vst", argv[0]) == 0) {
  1989.             vistype |= AUX_STENCIL;
  1990.         } else if (strcmp ("-vid", argv[0]) == 0 ) {
  1991.             if (argc == 1)
  1992.                 FATAL_ERROR ("viewperf: the -vid flag requires an argument.\n");
  1993.             vis_id = atoi (argv[1]);
  1994.             vis_criteria = AUX_USE_ID;
  1995.             strcpy( txcriteria , "ID" );
  1996.             ARG_INC;
  1997.         } else if (strcmp ("-vcriteria", argv[0]) == 0 || 
  1998.             strcmp ("-vcrit", argv[0]) == 0) {
  1999.             if (argc == 1)
  2000.                 FATAL_ERROR ("viewperf: the -vcriteria flag requires an argument.\n");
  2001.             if (strcmp ("EXACT", argv[1]) == 0) {
  2002.                 vis_criteria = AUX_EXACT_MATCH;
  2003.                 strcpy( txcriteria , "EXACT" );
  2004.             } else if (strcmp ("MIN", argv[1]) == 0) {
  2005.                 vis_criteria = AUX_MINIMUM_CRITERIA;
  2006.                 strcpy( txcriteria , "MINIMUM" );
  2007.             }
  2008.             ARG_INC;
  2009.         } else if (strcmp ("-singlebuffer", argv[0]) == 0 || 
  2010.             strcmp ("-sb", argv[0]) == 0) {
  2011.             renderDoubleBuffer = VP_FALSE;
  2012.         } else if (strcmp ("-ortho", argv[0]) == 0 || 
  2013.             strcmp ("-or", argv[0]) == 0) {
  2014.             orthomode = VP_TRUE;
  2015.         } else if (strcmp ("-nodither", argv[0]) == 0 || 
  2016.             strcmp ("-ndi", argv[0]) == 0) {
  2017.             dithermode = VP_FALSE;
  2018.         } else if (strcmp ("-blend", argv[0]) == 0 || 
  2019.             strcmp ("-bl", argv[0]) == 0) {
  2020.             blendmode = VP_TRUE;
  2021.         } else if (strcmp ("-zbuffer", argv[0]) == 0 || 
  2022.             strcmp ("-zb", argv[0]) == 0) {
  2023.             zbuffermode = VP_TRUE;
  2024.         } else if (strcmp ("-linestipple", argv[0]) == 0 || 
  2025.             strcmp ("-lp", argv[0]) == 0) {
  2026.             linestipplemode = VP_TRUE;
  2027.         } else if (strcmp ("-polystipple", argv[0]) == 0 || 
  2028.             strcmp ("-pp", argv[0]) == 0) {
  2029.             polystipplemode = VP_TRUE;
  2030.         } else if (strcmp ("-fog", argv[0]) == 0 || 
  2031.             strcmp ("-fg", argv[0]) == 0) {
  2032.             fogmode = VP_TRUE;
  2033.         } else if (strcmp ("-clip", argv[0]) == 0 || 
  2034.             strcmp ("-c", argv[0]) == 0) {
  2035.             clipmode = VP_TRUE;
  2036.         } else if (strcmp ("-lighttwoside", argv[0]) == 0 || 
  2037.             strcmp ("-l2s", argv[0]) == 0) {
  2038.             lighttwoside = GL_TRUE;
  2039.         } else if (strcmp ("-localview", argv[0]) == 0 || 
  2040.             strcmp ("-lv", argv[0]) == 0) {
  2041.             localviewmode = 1.0F;
  2042.         } else if (strcmp ("-toggle", argv[0]) == 0 || 
  2043.             strcmp ("-tg", argv[0]) == 0) {
  2044.             togglemode = VP_TRUE;
  2045.             if (argc == 1)
  2046.                 FATAL_ERROR ("viewperf: the -toggle flag requires an argument.\n");
  2047.             if (strcmp ("DEPTH_TEST", argv[1]) == 0) {
  2048.                 renderblock.capability = GL_DEPTH_TEST;
  2049.                 strcpy( txtoggle , "DEPTH_TEST" );
  2050.             } else if (strcmp ("DITHER", argv[1]) == 0) {
  2051.                 renderblock.capability = GL_DITHER;
  2052.                 strcpy( txtoggle , "DITHER" );
  2053.             } else if (strcmp ("LIGHTING", argv[1]) == 0) {
  2054.                 renderblock.capability = GL_LIGHTING;
  2055.                 strcpy( txtoggle , "LIGHTING" );
  2056.             } else if (strcmp ("LINE_STIPPLE", argv[1]) == 0) {
  2057.                 renderblock.capability = GL_LINE_STIPPLE;
  2058.                 strcpy( txtoggle , "LINE_STIPPLE" );
  2059.             } else if (strcmp ("BLEND", argv[1]) == 0) {
  2060.                 renderblock.capability = GL_BLEND;
  2061.                 strcpy( txtoggle , "BLEND" );
  2062.             } else if (strcmp ("POLYGON_STIPPLE", argv[1]) == 0) {
  2063.                 renderblock.capability = GL_POLYGON_STIPPLE;
  2064.                 strcpy( txtoggle , "POLYGON_STIPPLE" );
  2065.             } else if (strcmp ("LINE_WIDTH", argv[1]) == 0) {
  2066.                 togglelinewidthmode = VP_TRUE;
  2067.                 strcpy( txtoggle , "LINE_WIDTH" );
  2068.             } else if (strcmp ("MATRIX", argv[1]) == 0) {
  2069.                 togglematrixmode = VP_TRUE;
  2070.                 strcpy( txtoggle , "MATRIX" );
  2071.             }
  2072.  
  2073.             ARG_INC;
  2074.         } else if (strcmp ("-srcblendfunc", argv[0]) == 0 || 
  2075.             strcmp ("-sbf", argv[0]) == 0) {
  2076.             if (argc == 1)
  2077.                 FATAL_ERROR ("viewperf: the -srcblendfunc flag requires an argument.\n");
  2078.             if (strcmp ("ZERO", argv[1]) == 0) {
  2079.                 sblendfunc = GL_ZERO;
  2080.                 strcpy( txsblendfunc , "ZERO" );
  2081.             } else if (strcmp ("ONE", argv[1]) == 0) {
  2082.                 sblendfunc = GL_ONE;
  2083.                 strcpy( txsblendfunc , "ONE" );
  2084.             } else if (strcmp ("DST_COLOR", argv[1]) == 0) {
  2085.                 sblendfunc = GL_DST_COLOR;
  2086.                 strcpy( txsblendfunc , "DST_COLOR" );
  2087.             } else if (strcmp ("ONE_MINUS_DST_COLOR", argv[1]) == 0) {
  2088.                 sblendfunc = GL_ONE_MINUS_DST_COLOR;
  2089.                 strcpy( txsblendfunc , "ONE_MINUS_DST_COLOR" );
  2090.             } else if (strcmp ("SRC_ALPHA", argv[1]) == 0) {
  2091.                 sblendfunc = GL_SRC_ALPHA;
  2092.                 strcpy( txsblendfunc , "SRC_ALPHA" );
  2093.             } else if (strcmp ("ONE_MINUS_SRC_ALPHA", argv[1]) == 0) {
  2094.                 sblendfunc = GL_ONE_MINUS_SRC_ALPHA;
  2095.                 strcpy( txsblendfunc , "ONE_MINUS_SRC_ALPHA" );
  2096.             } else if (strcmp ("DST_ALPHA", argv[1]) == 0) {
  2097.                 sblendfunc = GL_DST_ALPHA;
  2098.                 strcpy( txsblendfunc , "DST_ALPHA" );
  2099.             } else if (strcmp ("ONE_MINUS_DST_ALPHA", argv[1]) == 0) {
  2100.                 sblendfunc = GL_ONE_MINUS_DST_ALPHA;
  2101.                 strcpy( txsblendfunc , "ONE_MINUS_DST_ALPHA" );
  2102.             } else if (strcmp ("SRC_ALPHA_SATURATE", argv[1]) == 0) {
  2103.                 sblendfunc = GL_SRC_ALPHA_SATURATE;
  2104.                 strcpy( txsblendfunc , "SRC_ALPHA_SATURATE" );
  2105.             }
  2106.             ARG_INC;
  2107.         } else if (strcmp ("-dstblendfunc", argv[0]) == 0 || 
  2108.             strcmp ("-dbf", argv[0]) == 0) {
  2109.             if (argc == 1)
  2110.                 FATAL_ERROR ("viewperf: the -dstblendfunc flag requires an argument.\n");
  2111.             if (strcmp ("ZERO", argv[1]) == 0) {
  2112.                 dblendfunc = GL_ZERO;
  2113.                 strcpy( txdblendfunc , "ZERO" );
  2114.  
  2115.             } else if (strcmp ("ONE", argv[1]) == 0) {
  2116.                 dblendfunc = GL_ONE;
  2117.                 strcpy( txdblendfunc , "ONE" );
  2118.  
  2119.             } else if (strcmp ("SRC_COLOR", argv[1]) == 0) {
  2120.                 dblendfunc = GL_SRC_COLOR;
  2121.                 strcpy( txdblendfunc , "SRC_COLOR" );
  2122.  
  2123.             } else if (strcmp ("ONE_MINUS_SRC_COLOR", argv[1]) == 0) {
  2124.                 dblendfunc = GL_ONE_MINUS_SRC_COLOR;
  2125.                 strcpy( txdblendfunc , "ONE_MINUS_SRC_COLOR" );
  2126.  
  2127.             } else if (strcmp ("SRC_ALPHA", argv[1]) == 0) {
  2128.                 dblendfunc = GL_SRC_ALPHA;
  2129.                 strcpy( txdblendfunc , "SRC_ALPHA" );
  2130.  
  2131.             } else if (strcmp ("ONE_MINUS_SRC_ALPHA", argv[1]) == 0) {
  2132.                 dblendfunc = GL_ONE_MINUS_SRC_ALPHA;
  2133.                 strcpy( txdblendfunc , "ONE_MINUS_SRC_ALPHA" );
  2134.  
  2135.             } else if (strcmp ("DST_ALPHA", argv[1]) == 0) {
  2136.                 dblendfunc = GL_DST_ALPHA;
  2137.                 strcpy( txdblendfunc , "DST_ALPHA" );
  2138.  
  2139.             } else if (strcmp ("ONE_MINUS_DST_ALPHA", argv[1]) == 0) {
  2140.                 dblendfunc = GL_ONE_MINUS_DST_ALPHA;
  2141.                 strcpy( txdblendfunc , "ONE_MINUS_DST_ALPHA" );
  2142.             }
  2143.             ARG_INC;
  2144.         } else if (strcmp ("-polysmooth", argv[0]) == 0 || 
  2145.             strcmp ("-ps", argv[0]) == 0) {
  2146.             polysmoothmode = VP_TRUE;
  2147.             sblendfunc = GL_SRC_ALPHA_SATURATE;
  2148.             strcpy( txsblendfunc , "SRC_ALPHA_SATURATE" );
  2149.             dblendfunc = GL_ONE;
  2150.             strcpy( txdblendfunc , "ONE" );
  2151.         } else if (strcmp ("-batch", argv[0]) == 0 || 
  2152.             strcmp ("-bt", argv[0]) == 0) {
  2153.             if (argc == 1)
  2154.                 FATAL_ERROR ("viewperf: the -batch flag requires an argument.\n");
  2155.             batchmode = VP_TRUE;
  2156.             numtobatch = atoi (argv[1]);
  2157.             ARG_INC;
  2158.         } else if (strcmp ("-colorper", argv[0]) == 0 || 
  2159.             strcmp ("-cp", argv[0]) == 0) {
  2160.             if (argc == 1)
  2161.                 FATAL_ERROR ("viewperf: the -colorper flag requires an argument.\n");
  2162.             if (strcmp ("FRAME", argv[1]) == 0) {
  2163.                 colormode = COLOR_PER_FRAME;
  2164.                 strcpy( txcolormode , "COLOR_PER_FRAME" );
  2165.             } else if (strcmp ("PRIMITIVE", argv[1]) == 0) {
  2166.                 colormode = COLOR_PER_PRIMITIVE;
  2167.                 strcpy( txcolormode , "COLOR_PER_PRIMITIVE" );
  2168.             } else if (strcmp ("VERTEX", argv[1]) == 0) {
  2169.                 colormode = COLOR_PER_VERTEX;
  2170.                 strcpy( txcolormode , "COLOR_PER_VERTEX" );
  2171.             }
  2172.             ARG_INC;
  2173.         } else if (strcmp ("-texcomp", argv[0]) == 0 || 
  2174.             strcmp ("-tc", argv[0]) == 0) {
  2175.             if (argc == 1)
  2176.                 FATAL_ERROR ("viewperf: the -texcomp flag requires an argument.\n");
  2177.             numcomp = atoi (argv[1]);
  2178.             if (numcomp < 1 || numcomp > 4)
  2179.                 numcomp = 3;
  2180.             ARG_INC;
  2181.         } else if (strcmp ("-texenv", argv[0]) == 0 || 
  2182.             strcmp ("-te", argv[0]) == 0) {
  2183.             if (argc == 1)
  2184.                 FATAL_ERROR ("viewperf: the -texenv flag requires an argument.\n");
  2185.             if (strcmp ("MODULATE", argv[1]) == 0) {
  2186.                 texenvmode = GL_MODULATE;
  2187.                 strcpy( txenv , "MODULATE" );
  2188.             } else if (strcmp ("BLEND", argv[1]) == 0) {
  2189.                 texenvmode = GL_BLEND;
  2190.                 strcpy( txenv , "BLEND" );
  2191.             } else if (strcmp ("DECAL", argv[1]) == 0) {
  2192.                 texenvmode = GL_DECAL;
  2193.                 strcpy( txenv , "DECAL" );
  2194.             }
  2195.             ARG_INC;
  2196.         } else if (strcmp ("-texgen", argv[0]) == 0 || 
  2197.             strcmp ("-txg", argv[0]) == 0) {
  2198.             if (argc == 1)
  2199.                 FATAL_ERROR ("viewperf: the -texgen flag requires an argument.\n");
  2200.             texgenmode = TXG_EYE_LINEAR;
  2201.             strcpy( txfile , argv[1]);
  2202. #ifdef SEARCHPATH
  2203.             {
  2204.                 char* texpath = getenv("VPTEXPATH");
  2205.                 char* dataPath;
  2206.                 char  filenameptr[512];
  2207.                 char* defaultPath = ".:./data/textures:/";
  2208.                 if (texpath == 0)
  2209.                     texpath = defaultPath;
  2210.                 else if (*texpath == 0)
  2211.                     texpath = defaultPath;
  2212.                 if (txfile) {
  2213.                     strcpy(filenameptr, txfile);
  2214.                     dataPath = SearchPath(texpath, filenameptr);
  2215.                     if (dataPath == NULL)
  2216.                         FATAL_ERROR("Couldn't open texture file\n");
  2217.                     /* Add dataPath to the beginning of txfile */
  2218.                     strcat(dataPath, "/");
  2219.                     strcpy(txfile, strcat(dataPath, txfile));
  2220.                 }
  2221.             }
  2222. #endif
  2223.             if ((texfile = fopen(txfile, BINARY_FILE) ) == 0) {
  2224.                 FATAL_ERROR("Can't open texture file\n");
  2225.             }
  2226.             ARG_INC;
  2227.             if( (argc != 1) && (argv[1][0] != '-') )
  2228.             {
  2229.                 if(!strcmp(argv[1], "OBJECT_LINEAR"))
  2230.                     texgenmode = TXG_OBJECT_LINEAR;
  2231.                 else
  2232.                     if(!strcmp(argv[1], "SPHERE_MAP"))
  2233.                         texgenmode = TXG_SPHERE_MAP;
  2234.             }
  2235.         }
  2236.         else 
  2237.             if (strcmp ("-texture", argv[0]) == 0 || 
  2238.                 strcmp ("-tx", argv[0]) == 0)
  2239.             {
  2240.                 if (argc == 1)
  2241.                     FATAL_ERROR ("viewperf: the -texture flag requires an argument.\n");
  2242.                 texturemode = VP_TRUE;
  2243.                 strcpy( txfile , argv[1]);
  2244. #ifdef SEARCHPATH
  2245.                 {
  2246.                     char* texpath = getenv("VPTEXPATH");
  2247.                     char* dataPath;
  2248.                     char  filenameptr[512];
  2249.                     char* defaultPath = ".:./data/textures:/";
  2250.                     if (texpath == 0)
  2251.                         texpath = defaultPath;
  2252.                     else if (*texpath == 0)
  2253.                         texpath = defaultPath;
  2254.                     if (txfile) {
  2255.                         strcpy(filenameptr, txfile);
  2256.                         dataPath = SearchPath(texpath, filenameptr);
  2257.                         if (dataPath == NULL)
  2258.                             FATAL_ERROR("Couldn't open texture file\n");
  2259.                         /* Add dataPath to the beginning of txfile */
  2260.                         strcat(dataPath, "/");
  2261.                         strcpy(txfile, strcat(dataPath, txfile));
  2262.                     }
  2263.                 }
  2264. #endif
  2265.                 if ((texfile = fopen(txfile, BINARY_FILE) ) == 0) {
  2266.                     FATAL_ERROR("Can't open texture file\n");
  2267.                 }
  2268.                 ARG_INC;
  2269.             } 
  2270.             else if (strcmp ("-minfilter", argv[0]) == 0 || 
  2271.                 strcmp ("-minf", argv[0]) == 0) {
  2272.                 if (argc == 1)
  2273.                     FATAL_ERROR ("viewperf: the -minfilter flag requires an argument.\n");
  2274.                 if (strcmp ("NEAREST", argv[1]) == 0) {
  2275.                     minfilter = GL_NEAREST;
  2276.                     strcpy( txmin , "NEAREST" );
  2277.                 } else if (strcmp ("LINEAR", argv[1]) == 0) {
  2278.                     minfilter = GL_LINEAR;
  2279.                     strcpy( txmin , "LINEAR" );
  2280.                 } else if (strcmp ("NEAREST_MIPMAP_NEAREST", argv[1]) == 0) {
  2281.                     minfilter = GL_NEAREST_MIPMAP_NEAREST;
  2282.                     strcpy( txmin , "NEAREST_MIPMAP_NEAREST" );
  2283.                 } else if (strcmp ("LINEAR_MIPMAP_LINEAR", argv[1]) == 0) {
  2284.                     minfilter = GL_LINEAR_MIPMAP_LINEAR;
  2285.                     strcpy( txmin , "LINEAR_MIPMAP_LINEAR" );
  2286.                 } else if (strcmp ("NEAREST_MIPMAP_LINEAR", argv[1]) == 0) {
  2287.                     minfilter = GL_NEAREST_MIPMAP_LINEAR;
  2288.                     strcpy( txmin , "NEAREST_MIPMAP_LINEAR" );
  2289.                 } else if (strcmp ("LINEAR_MIPMAP_LINEAR", argv[1]) == 0) {
  2290.                     minfilter = GL_LINEAR_MIPMAP_LINEAR;
  2291.                     strcpy( txmin , "LINEAR_MIPMAP_LINEAR" );
  2292.                 }
  2293.                 ARG_INC;
  2294.             } 
  2295.             else if (strcmp ("-magfilter", argv[0]) == 0 || 
  2296.                 strcmp ("-magf", argv[0]) == 0) {
  2297.                 if (argc == 1)
  2298.                     FATAL_ERROR ("viewperf: the -magfilter flag requires an argument.\n");
  2299.                 if (strcmp ("NEAREST", argv[1]) == 0) {
  2300.                     magfilter = GL_NEAREST;
  2301.                     strcpy( txmag , "NEAREST" );
  2302.                 } else if (strcmp ("LINEAR", argv[1]) == 0) {
  2303.                     magfilter = GL_LINEAR;
  2304.                     strcpy( txmag , "LINEAR" );
  2305.                 }
  2306.                 ARG_INC;
  2307.             } 
  2308.             else if (strcmp ("-colormaterial", argv[0]) == 0 || 
  2309.                 strcmp ("-cm", argv[0]) == 0) {
  2310.                 if (argc < 3)
  2311.                     FATAL_ERROR ("viewperf: the -colormaterial flag requires 2 arguments.\n");
  2312.                 if (strcmp ("FRONT", argv[1]) == 0) {
  2313.                     cmface = GL_FRONT;
  2314.                     strcpy( cmfaceString , "FRONT" );
  2315.                 } else if (strcmp ("BACK", argv[1]) == 0) {
  2316.                     cmface = GL_BACK;
  2317.                     strcpy( cmfaceString , "BACK" );
  2318.                 } else if (strcmp ("FRONT_AND_BACK", argv[1]) == 0) {
  2319.                     cmface = GL_FRONT_AND_BACK;
  2320.                     strcpy( cmfaceString , "FRONT_AND_BACK" );
  2321.                 }
  2322.                 if (strcmp ("EMISSION", argv[2]) == 0) {
  2323.                     cmmode = GL_EMISSION;
  2324.                     strcpy( cmmodeString , "EMISSION" );
  2325.                 } else if (strcmp ("AMBIENT", argv[2]) == 0) {
  2326.                     cmmode = GL_AMBIENT;
  2327.                     strcpy( cmmodeString , "AMBIENT" );
  2328.                 } else if (strcmp ("DIFFUSE", argv[2]) == 0) {
  2329.                     cmmode = GL_DIFFUSE;
  2330.                     strcpy( cmmodeString , "DIFFUSE" );
  2331.                 } else if (strcmp ("SPECULAR", argv[2]) == 0) {
  2332.                     cmmode = GL_SPECULAR;
  2333.                     strcpy( cmmodeString , "SPECULAR" );
  2334.                 } else if (strcmp ("AMBIENT_AND_DIFFUSE", argv[2]) == 0) {
  2335.                     cmmode = GL_AMBIENT_AND_DIFFUSE;
  2336.                     strcpy( cmmodeString , "AMBIENT_AND_DIFFUSE" );
  2337.                 }
  2338.                 ARG_INC;
  2339.             } 
  2340.             else if (strcmp ("-polymodefront", argv[0]) == 0 || 
  2341.                 strcmp ("-pmf", argv[0]) == 0) {
  2342.                 if (argc == 1)
  2343.                     FATAL_ERROR ("viewperf: the -polymodefront flag requires an argument.\n");
  2344.                 if (strcmp ("FILL", argv[1]) == 0) {
  2345.                     polymodefront = GL_FILL;
  2346.                     strcpy( txpmf , "FILL" );
  2347.                 } else if (strcmp ("POINT", argv[1]) == 0) {
  2348.                     polymodefront = GL_POINT;
  2349.                     strcpy( txpmf , "POINT" );
  2350.                 } else if (strcmp ("LINE", argv[1]) == 0) {
  2351.                     polymodefront = GL_LINE;
  2352.                     strcpy( txpmf , "LINE" );
  2353.                 }
  2354.                 ARG_INC;
  2355.             } 
  2356.             else if (strcmp ("-polymodeback", argv[0]) == 0 || 
  2357.                 strcmp ("-pmb", argv[0]) == 0) {
  2358.                 if (argc == 1)
  2359.                     FATAL_ERROR ("viewperf: the -polymodeback flag requires an argument.\n");
  2360.                 if (strcmp ("FILL", argv[1]) == 0) {
  2361.                     polymodeback = GL_FILL;
  2362.                     strcpy( txpmb , "FILL" );
  2363.                 } else if (strcmp ("POINT", argv[1]) == 0) {
  2364.                     polymodeback = GL_POINT;
  2365.                     strcpy( txpmb , "POINT" );
  2366.                 } else if (strcmp ("LINE", argv[1]) == 0) {
  2367.                     polymodeback = GL_LINE;
  2368.                     strcpy( txpmb , "LINE" );
  2369.                 }
  2370.                 ARG_INC;
  2371.             } 
  2372.             else if (strcmp ("-triangle", argv[0]) == 0 || 
  2373.                 strcmp ("-tr", argv[0]) == 0) {
  2374.                 if (argc == 1)
  2375.                     FATAL_ERROR ("viewperf: the -triangle flag requires an argument.\n");
  2376.                 objnameptr = strcpy(objnameptr, argv[1]);
  2377.                 inputmode = TRIINPUT;
  2378.                 ARG_INC;
  2379.             } 
  2380.             else if (strcmp ("-quad", argv[0]) == 0 || 
  2381.                 strcmp ("-qd", argv[0]) == 0) {
  2382.                 if (argc == 1)
  2383.                     FATAL_ERROR ("viewperf: the -quad flag requires an argument.\n");
  2384.                 objnameptr = strcpy(objnameptr, argv[1]);
  2385.                 inputmode = QUADINPUT;
  2386.                 ARG_INC;
  2387.             } 
  2388.             else if (strcmp ("-mesh", argv[0]) == 0 || 
  2389.                 strcmp ("-mh", argv[0]) == 0) {
  2390.                 if (argc == 1)
  2391.                     FATAL_ERROR ("viewperf: the -mesh flag requires an argument.\n");
  2392.                 objnameptr = strcpy(objnameptr, argv[1]);
  2393.                 inputmode = MESHINPUT;
  2394.                 ARG_INC;
  2395.             } 
  2396.             else if (strcmp ("-polygon", argv[0]) == 0 || 
  2397.                 strcmp ("-pg", argv[0]) == 0) {
  2398.                 if (argc == 1)
  2399.                     FATAL_ERROR ("viewperf: the -polygon flag requires an argument.\n");
  2400.                 objnameptr = strcpy(objnameptr, argv[1]);
  2401.                 inputmode = POLYGONINPUT;
  2402.                 ARG_INC;
  2403.             } 
  2404.             else if (strcmp ("-walkthru", argv[0]) == 0 || 
  2405.                 strcmp ("-wt", argv[0]) == 0) {
  2406.                 walkthrumode = VP_TRUE;
  2407.             } 
  2408.             else if (strcmp ("-linewidth", argv[0]) == 0 || 
  2409.                 strcmp ("-lw", argv[0]) == 0) {
  2410.                 if (argc == 1)
  2411.                     FATAL_ERROR ("viewperf: the -linewidth flag requires an argument.\n");
  2412.                 linewidthmode = atof (argv[1]);
  2413.                 ARG_INC;
  2414.             } 
  2415.             else if (strcmp ("-xwinsize", argv[0]) == 0 || 
  2416.                 strcmp ("-xws", argv[0]) == 0) {
  2417.                 if (argc == 1)
  2418.                     FATAL_ERROR ("viewperf: the -xwinsize flag requires an argument.\n");
  2419.                 environ.windowWidth = atoi (argv[1]);
  2420.                 ARG_INC;
  2421.             } 
  2422.             else if (strcmp ("-ywinsize", argv[0]) == 0 || 
  2423.                 strcmp ("-yws", argv[0]) == 0) {
  2424.                 if (argc == 1)
  2425.                     FATAL_ERROR ("viewperf: the -ywinsize flag requires an argument.\n");
  2426.                 environ.windowHeight = atoi (argv[1]);
  2427.                 ARG_INC;
  2428.             } 
  2429.             else if (strcmp ("-numframes", argv[0]) == 0 || 
  2430.                 strcmp ("-nf", argv[0]) == 0) {
  2431.                 if (argc == 1)
  2432.                     FATAL_ERROR ("viewperf: the -numframes flag requires an argument.\n");
  2433.                 eventblock.numframes = atoi (argv[1]);
  2434.                 if (eventblock.numframes <= 0)
  2435.                     FATAL_ERROR ("viewperf: You'll need more frames than this\n");
  2436.                 ARG_INC;
  2437.             } 
  2438.             else if (strcmp ("-numilights", argv[0]) == 0 || 
  2439.                 strcmp ("-nil", argv[0]) == 0) {
  2440.                 if (argc == 1)
  2441.                     FATAL_ERROR ("viewperf: the -numilights flag requires an argument.\n");
  2442.                 numInfiniteLights = atoi (argv[1]);
  2443.                 if (numInfiniteLights < 0)
  2444.                     FATAL_ERROR ("viewperf: Number of infinite lights must be positive.\n");
  2445.                 if (numInfiniteLights + numLocalLights > 8)
  2446.                     FATAL_ERROR ("viewperf: Total number of lights enabled must be less than or equal to 8.\n");
  2447.                 ARG_INC;
  2448.             } 
  2449.             else if (strcmp ("-numllights", argv[0]) == 0 || 
  2450.                 strcmp ("-nll", argv[0]) == 0) {
  2451.                 if (argc == 1)
  2452.                     FATAL_ERROR ("viewperf: the -numllights flag requires an argument.\n");
  2453.                 numLocalLights = atoi (argv[1]);
  2454.                 if (numLocalLights < 0)
  2455.                     FATAL_ERROR ("viewperf: Number of local lights must be positive.\n");
  2456.                 if (numInfiniteLights + numLocalLights > 8)
  2457.                     FATAL_ERROR ("viewperf: Total number of lights enabled must be less than or equal to 8.\n");
  2458.                 ARG_INC;
  2459.             } 
  2460.             else if (strcmp ("-minperiod", argv[0]) == 0 || 
  2461.                 strcmp ("-mp", argv[0]) == 0) {
  2462.                 if (argc == 1)
  2463.                     FATAL_ERROR ("viewperf: the -minperiod flag requires an argument.\n");
  2464.                 eventblock.minperiod = atof (argv[1]);
  2465.                 ARG_INC;
  2466. #ifdef MP
  2467.             } 
  2468.             else if (strcmp ("-threads", argv[0]) == 0 ||
  2469.                 strcmp ("-th", argv[0]) == 0) {
  2470.                 if ((argc > 1) && (isdigit(*argv[1]))) {
  2471.                     eventblock.threads = atoi (argv[1]);
  2472.                     ARG_INC;
  2473.                 } else {
  2474.                     eventblock.threads = numProcessors ();
  2475.                 }
  2476.                 if (eventblock.threads < 1)
  2477.                     FATAL_ERROR ("viewperf: the minimum number of threads is 1.\n");
  2478. #endif
  2479.             } 
  2480.             else if (strcmp ("-help", argv[0]) == 0 || 
  2481.                 strcmp ("-usage", argv[0]) == 0 || 
  2482.                 strcmp ("-h", argv[0]) == 0 || 
  2483.                 strcmp ("-u", argv[0]) == 0) {
  2484.                 fprintf (stdout, "viewperf version %s:\n", VERSION);
  2485.                 fprintf (stdout, "\
  2486. Program options:\n\
  2487. -polygon -pg   <file>  : Viewpoint object to be used in the tests\n\
  2488. -triangle -tr  <file>  : Viewpoint object to be used in the tests\n\
  2489. -quad -qd      <file>  : Viewpoint object to be used in the tests\n\
  2490. -mesh -mh      <file>  : Mesh object to be used in the tests\n\
  2491. -rendermode -rm <mode> : POINT, VECTOR, LINE, POLYGON, TMESH, TFAN,\n\
  2492.                          TRIANGLE, or QUAD - default LINE\n\
  2493. -vcriteria -vcrit      : AUX Visual selection criteria - EXACT, MIN\n\
  2494.                          - default MIN\n\
  2495. -vid <id>              : Ask AUX for visual with ID = <id>\n\
  2496. -vaccum -vac           : Ask AUX for an accumulation buffer visual\n\
  2497. -valpha -val           : Ask AUX for an alpha buffer visual\n\
  2498. -vdepthbuffer -vz      : Ask AUX for a depth buffer visual\n\
  2499. -vstencil -vst         : Ask AUX for a stencil buffer visual\n\
  2500. -indirectrender -ir    : Render indirect - default direct\n\
  2501. -nodither -ndi         : Disable dithering\n\
  2502. -ortho -or             : Parallel/Orthographic projection - default Perspective\n\
  2503. -displaylist -dl       : Render with display list mode\n\
  2504. -colorper -cp  <mode>  : FRAME = Color per Frame,\n\
  2505.                        : PRIMITIVE = Color per Primitive,\n\
  2506.                        : VERTEX = Color per Vertex - default FRAME\n\
  2507. -texture -tx   <file>  : MTV image for texturing\n\
  2508. -texgen -txg <file> <mode> : <file> is MTV image for environment mapping\n\
  2509.                          <mode> is SPHERE_MAP, OBJECT_LINEAR, EYE_LINEAR\n\
  2510.                          - default EYE_LINEAR\n\
  2511. -magfilter -magf <flt> : NEAREST, LINEAR - default NEAREST\n\
  2512. -minfilter -minf <flt> : NEAREST, LINEAR, NEAREST_MIPMAP_NEAREST,\n\
  2513.                          LINEAR_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR,\n\
  2514.                          LINEAR_MIPMAP_LINEAR - default NEAREST\n\
  2515. -texenv -te <env>      : Texture environment, MODULATE, DECAL, BLEND\n\
  2516.                          - default DECAL\n\
  2517. -texcomp -tc <num>     : Texture components where <num> is 1,2,3, or 4\n\
  2518.                        : -default 3\n\
  2519. ");
  2520.                 fprintf (stdout, "\
  2521. -blend -bl             : Enable Blending\n\
  2522. -srcblendfunc -sbf     : ZERO, ONE, DST_COLOR, ONE_MINUS_DST_COLOR, SRC_ALPHA,\n\
  2523.                          ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA,\n\
  2524.                          SRC_ALPHA_SATURATE - default SRC_ALPHA\n\
  2525. -dstblendfunc -dbf     : ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, SRC_ALPHA,\n\
  2526.                          ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA,\n\
  2527.                          - default ONE_MINUS_SRC_ALPHA\n\
  2528. -linewidth -lw <width> : Linewidth for wire/vector tests - default 1.0\n\
  2529. -xwinsize -xws <side>  : Size of test windows X dimension - default 700\n\
  2530. -ywinsize -yws <side>  : Size of test windows Y dimension - default 700\n\
  2531. -numframes -nf <num>   : Number of frames to be rendered during measurement\n\
  2532.                          Takes priority over -mp\n\
  2533. -numilights -nil <num> : Turns on <num> infinite lights - default 0\n\
  2534. -numllights -nll <num> : Turns on <num> local lights - default 0\n\
  2535. ");
  2536.                 fprintf (stdout, "\
  2537. -colormaterial -cm <side> <mode> :\n\
  2538.                          <side> is FRONT, BACK, FRONT_AND_BACK - default FRONT\n\
  2539.                          <mode> is AMBIENT, DIFFUSE, EMISSION, SPECULAR,\n\
  2540.                          AMBIENT_AND_DIFFUSE - default AMBIENT_AND_DIFFUSE\n\
  2541. -backface -bf          : Cull Backfacing primitives - default off\n\
  2542. -frontface -ff         : Cull Frontfacing primitives - default off\n\
  2543. -singlebuffer -sb      : Single buffer mode\n\
  2544. -fog -fg               : Enable fog\n\
  2545. -linesmooth -ls        : Enable line antialiasing\n\
  2546. -polysmooth -ps        : Enable polygon antialiasing\n\
  2547. -facetnormal -fn       : Use facet normals when lighting\n\
  2548. -linestipple -lp       : Enable line stipple\n\
  2549. -polystipple -pp       : Enable polygon stipple\n\
  2550. -toggle -tg <cap>      : Toggle per primitive - BLEND, DEPTH_TEST, DITHER,\n\
  2551.                          LIGHTING, LINE_WIDTH, LINE_STIPPLE, POLYGON_STIPPLE,\n\
  2552.                          or MATRIX - multmatrix\n\
  2553. -batch -bt <num>       : Batch <num> primitives together per glBegin/glEnd\n\
  2554.                          Valid with POINT, VECTOR, TRIANGLE, and QUADS\n\
  2555. -polymodefront -pmf    : POINT, LINE, or FILL - default FILL\n\
  2556. -polymodeback  -pmb    : POINT, LINE, or FILL - default FILL\n\
  2557. -flat -f               : Set shademodel to FLAT - default GOURAUD\n\
  2558. -zbuffer -zb           : Enable zbuffer for tests - default off\n\
  2559. ");
  2560.                 fprintf (stdout, "\
  2561. -clip -c               : Align object on 3D clip boundary\n\
  2562. -lighttwoside -l2s     : Light both sides of model\n\
  2563. -localview -lv         : Define local viewer for lit tests\n\
  2564. -minperiod -mp <num>   : Set minimum testing period in seconds\n\
  2565. -mblur <num>           : Use motion blur with num being amount of decay\n\
  2566. -aa_multi <x> <r>      : Full scene antialiasing rendered x times at an\n\
  2567.                        : offset of r.  r should be tuned to the viewset\n\
  2568. -walkthru -wt          : Walkthru mode\n\
  2569. ");
  2570. #ifdef MP
  2571.                 fprintf (stdout, "\
  2572. -threads -th <num>     : Sets number of threads (no arg means 1 per processor)\n\
  2573. ");
  2574. #endif
  2575.                 exit(0);
  2576.             }
  2577.     }
  2578.  
  2579.  
  2580.     /*********************************************************************/
  2581.     /*                                                                   */
  2582.     /*                        Test Description                           */
  2583.     /*                                                                   */
  2584.     /*********************************************************************/
  2585.  
  2586.  
  2587.     strcpy( desc , "\0" );
  2588.  
  2589.     /* Input mode & Object */
  2590.     strcat( desc , inputmodetx[ inputmode ] );
  2591.     ptr=(ptr=strrchr(objnameptr,'/')) == NULL ? ptr=objnameptr : ++ptr;
  2592.     strcat( desc , ptr );
  2593.     strcat( desc , " ");
  2594.  
  2595.     /* -rm */
  2596.     strcat( desc , "-rm ");
  2597.     strcat(desc, rendermodetext[rendermode]);
  2598.     strcat( desc, " ");
  2599.  
  2600.     /* -cm */
  2601.     if (colormode != COLOR_PER_FRAME && numInfiniteLights + numLocalLights > 0) {
  2602.         cmenable = VP_TRUE;
  2603.     }
  2604.  
  2605.     /* -nf and -mp */
  2606.     if (eventblock.numframes > 0) {
  2607.         eventblock.minperiod = 0.0F;
  2608.         sprintf( tempstring , "-nf %d \0", eventblock.numframes);
  2609.         strcat( desc , tempstring );
  2610.     } else if (eventblock.minperiod != MIN_TEST_TIME) {
  2611.         if ((float)floor(eventblock.minperiod) == eventblock.minperiod) {
  2612.             int mp = (int)eventblock.minperiod;
  2613.             sprintf( tempstring , "-mp %d \0", mp);
  2614.             strcat( desc , tempstring );
  2615.         } else {
  2616.             sprintf( tempstring , "-mp %f \0", eventblock.minperiod);
  2617.             strcat( desc , tempstring );
  2618.         }
  2619.     }
  2620.  
  2621.     /* -cp */
  2622.     strcat( desc , "-cp ");
  2623.     strcat(desc, cptx[colormode]);
  2624.  
  2625.     strcat( desc , dr[environ.directRender]);
  2626.     strcat( desc , dl[displaylistmode]);
  2627.     strcat( desc , db[renderDoubleBuffer]);
  2628.     strcat( desc , zb[zbuffermode]);
  2629.     strcat( desc , fg[fogmode]);
  2630.     /* -bt */
  2631.     if ( numtobatch != 0 ) {
  2632.         sprintf( tempstring,"-bt %d \0",numtobatch);
  2633.         strcat( desc, tempstring );
  2634.     }
  2635.     strcat( desc , shade[shademodelmode == GL_FLAT]);
  2636.     /* -nil */
  2637.     if ( numInfiniteLights > 0 ) {
  2638.         sprintf( tempstring , "-nil %d \0", numInfiniteLights);
  2639.         strcat( desc , tempstring );
  2640.     }
  2641.     /* -nll */
  2642.     if ( numLocalLights > 0 ) {
  2643.         sprintf( tempstring , "-nll %d \0", numLocalLights);
  2644.         strcat( desc , tempstring );
  2645.     }
  2646.     if ( cmenable && ( cmface != GL_FRONT || cmmode != GL_AMBIENT_AND_DIFFUSE ) ) {
  2647.         sprintf( tempstring , "-cm %s %s \0", cmfaceString, cmmodeString);
  2648.         strcat( desc , tempstring );
  2649.     }
  2650.     strcat( desc , lv[(int)localviewmode]);
  2651.     strcat( desc , l2s[lighttwoside]);
  2652.     strcat( desc , or[orthomode]);
  2653.     strcat( desc , fn[facetnormalmode]);
  2654.     strcat( desc , bf[backfacemode]);
  2655.     strcat( desc , ff[frontfacemode]);
  2656.     strcat( desc , pp[polystipplemode]);
  2657.     strcat( desc , ps[polysmoothmode]);
  2658.     strcat( desc , lp[linestipplemode]);
  2659.     strcat( desc , ls[linesmoothmode]);
  2660.     /* -lw */
  2661.     if ( linewidthmode > 1.0 ) {
  2662.         sprintf( tempstring , "-lw %0.1f \0", linewidthmode);
  2663.         strcat( desc , tempstring );
  2664.     }
  2665.     strcat( desc , di[dithermode]);
  2666.     strcat( desc , clip[clipmode]);
  2667.     /* -pmf */
  2668.     if (strcmp("FILL", txpmf) != 0) {
  2669.         sprintf(tempstring,"-pmf %s \0",txpmf);
  2670.         strcat(desc,tempstring);
  2671.     }
  2672.     /* -pmb */
  2673.     if (strcmp("FILL", txpmb) != 0) {
  2674.         sprintf(tempstring,"-pmb %s \0",txpmb);
  2675.         strcat(desc,tempstring);
  2676.     }
  2677.  
  2678.     /* -tg */
  2679.     if (togglemode) {
  2680.         sprintf(tempstring,"-tg %s \0",txtoggle);
  2681.         strcat(desc,tempstring);
  2682.     }
  2683.  
  2684.     strcat( desc , bl[blendmode]);
  2685.     /* -sbf */
  2686.     if (strcmp("SRC_ALPHA",txsblendfunc)!=0) {
  2687.         sprintf(tempstring,"-sbf %s \0",txsblendfunc);
  2688.         strcat(desc,tempstring);
  2689.     }
  2690.     /* -dbf */
  2691.     if (strcmp("ONE_MINUS_SRC_ALPHA",txdblendfunc)!=0) {
  2692.         sprintf(tempstring,"-dbf %s \0",txdblendfunc);
  2693.         strcat(desc,tempstring);
  2694.     }
  2695.     /* -tx */
  2696.     if( texturemode )
  2697.     {
  2698.         ptr=(ptr=strrchr(txfile,'/')) == NULL ? ptr=txfile : ++ptr;
  2699.         sprintf(tempstring,"-tx %s ", ptr);
  2700.         strcat( desc , tempstring );
  2701.         if (strcmp("NEAREST", txmag) != 0) {
  2702.             sprintf(tempstring,"-magf %s \0",txmag);
  2703.             strcat(desc,tempstring);
  2704.         }
  2705.         if (strcmp("NEAREST", txmin) != 0) {
  2706.             sprintf(tempstring,"-minf %s \0",txmin);
  2707.             strcat(desc,tempstring);
  2708.         }
  2709.         if (strcmp("DECAL", txenv) != 0)   {
  2710.             sprintf(tempstring,"-te %s \0"  ,txenv);
  2711.             strcat(desc,tempstring);
  2712.         }
  2713.         if ( numcomp != 3)                 {
  2714.             sprintf(tempstring,"-tc %d \0"  ,numcomp);
  2715.             strcat(desc,tempstring);
  2716.         }
  2717.     }
  2718.  
  2719.     /* -txg */
  2720.     if( texgenmode )
  2721.     {
  2722.         ptr=(ptr=strrchr(txfile,'/')) == NULL ? ptr=txfile : ++ptr;
  2723.         sprintf(tempstring,"-txg %s %s ", ptr, texture_generation_mode[texgenmode]);
  2724.         strcat( desc , tempstring );
  2725.         if (strcmp("NEAREST", txmag) != 0) {
  2726.             sprintf(tempstring,"-magf %s \0",txmag);
  2727.             strcat(desc,tempstring);
  2728.         }
  2729.         if (strcmp("NEAREST", txmin) != 0) {
  2730.             sprintf(tempstring,"-minf %s \0",txmin);
  2731.             strcat(desc,tempstring);
  2732.         }
  2733.         if (strcmp("DECAL", txenv) != 0)   {
  2734.             sprintf(tempstring,"-te %s \0"  ,txenv);
  2735.             strcat(desc,tempstring);
  2736.         }
  2737.         if ( numcomp != 3)                 {
  2738.             sprintf(tempstring,"-tc %d \0"  ,numcomp);
  2739.             strcat(desc,tempstring);
  2740.         }
  2741.     }
  2742.  
  2743.     /*  -xws, -yws */
  2744.     if( environ.windowWidth != X_WINDOW_SIZE )  {
  2745.         sprintf( tempstring , "-xws %d ",environ.windowWidth);
  2746.         strcat( desc , tempstring );
  2747.     }
  2748.     if( environ.windowHeight != Y_WINDOW_SIZE )  {
  2749.         sprintf( tempstring , "-yws %d ",environ.windowHeight);
  2750.         strcat( desc , tempstring );
  2751.     }
  2752.  
  2753.     /* -vcrit */
  2754.     if ( vis_criteria == AUX_EXACT_MATCH ) strcat( desc , "-vcrit EXACT ");
  2755.     strcat( desc , vac[(vistype & AUX_ACCUM) == AUX_ACCUM]);
  2756.     strcat( desc , val[(vistype & AUX_ALPHA) == AUX_ALPHA]);
  2757.     strcat( desc , vz[(vistype & AUX_DEPTH) == AUX_DEPTH]);
  2758.     strcat( desc , vst[(vistype & AUX_STENCIL) == AUX_STENCIL]);
  2759.  
  2760.     /* -mblur */
  2761.     if(mblurmode) {
  2762.         sprintf( tempstring, "-mblur %f ", blur_amount);
  2763.         strcat( desc, tempstring);
  2764.     }
  2765.  
  2766.     /* -aa_multi */
  2767.     if(fsantimode) {
  2768.         sprintf(tempstring, "-aa_multi %d %f ", fsaredraw, fsajitter);
  2769.         strcat(desc, tempstring);
  2770.     }
  2771.  
  2772.     /* -walkthru */
  2773.     if(walkthrumode) {
  2774.         sprintf(tempstring, "-wt ");
  2775.         strcat(desc, tempstring);
  2776.     }
  2777.  
  2778.     /*********************************************************************/
  2779.     /*                                                                   */
  2780.     /*                      Open Window                                  */
  2781.     /*                                                                   */
  2782.     /*********************************************************************/
  2783.  
  2784.     /* if the user didn't select any visual buffers 
  2785.        then select some for him */
  2786.  
  2787.     if (vistype == 0) {
  2788.         if (zbuffermode)
  2789.             vistype |= AUX_DEPTH;
  2790.         if (blendmode && (sblendfunc == GL_DST_ALPHA ||
  2791.             sblendfunc == GL_ONE_MINUS_DST_ALPHA ||
  2792.             sblendfunc == GL_SRC_ALPHA_SATURATE ||
  2793.             dblendfunc == GL_DST_ALPHA ||
  2794.             dblendfunc == GL_ONE_MINUS_DST_ALPHA))
  2795.             vistype |= AUX_ALPHA;
  2796.     }
  2797.  
  2798.     /* Add these to what the user or viewperf selected */
  2799.  
  2800.     vistype |= AUX_RGB;
  2801.     vistype |= (renderDoubleBuffer) ? AUX_DOUBLE : AUX_SINGLE;
  2802.     vistype |= (environ.directRender) ? AUX_DIRECT : AUX_INDIRECT;
  2803.  
  2804.     /* set AUX visual selection criteria */
  2805.  
  2806.     auxInitDisplayModePolicy(vis_criteria);
  2807.     if (vis_criteria == AUX_USE_ID )
  2808.         auxInitDisplayModeID(vis_id);
  2809.     else
  2810.         auxInitDisplayMode(vistype);
  2811.  
  2812.     /* Open the window */
  2813.  
  2814.     auxInitPosition(0, 0, environ.windowWidth, environ.windowHeight);
  2815.     if (auxInitWindow("Viewperf") == GL_FALSE) {
  2816.         fprintf(stderr, "AUX couldn't find a visual matching the given criteria\n");
  2817.         auxQuit();
  2818.     }
  2819.  
  2820.     /* Begin Windowing System Dependent */
  2821. #ifdef WIN32
  2822.     eventblock.window = auxGetHWND();
  2823.     eventblock.display = auxGetHDC();
  2824. #elif !defined(OS2) && !defined(__amigaos__)
  2825.     eventblock.window = auxXWindow();
  2826.     eventblock.display = auxXDisplay();
  2827. #endif
  2828.     NullEnvironmentData(&environ);
  2829.     GetEnvironment(&environ);
  2830.  
  2831.     /* End Windowing System Dependent */
  2832.  
  2833.     /*********************************************************************/
  2834.     /*                                                                   */
  2835.     /*                      Render title screen                          */
  2836.     /*                                                                   */
  2837.     /*********************************************************************/
  2838.  
  2839.     glClearColor(0.0F, 0.0F, 0.0F, 1.0F);
  2840.     glDrawBuffer(GL_FRONT_AND_BACK);
  2841.     glClear(GL_COLOR_BUFFER_BIT);
  2842.     if (renderDoubleBuffer && environ.bufConfig.doubleBuffer)
  2843.         glDrawBuffer(GL_BACK);
  2844.     else
  2845.         glDrawBuffer(GL_FRONT);
  2846.  
  2847.  
  2848.     glMatrixMode(GL_PROJECTION);
  2849.     glLoadIdentity();
  2850.     glOrtho(0.0F, 1280.0F, 0.0F, 1024.0F, 1.0F, -1.0F);
  2851.     glMatrixMode(GL_MODELVIEW);
  2852.     glLoadIdentity();
  2853.  
  2854.     glShadeModel(GL_SMOOTH);
  2855.  
  2856.     glBegin(GL_QUADS);
  2857.     glColor3f(1.0F, 0.9F, 0.3F);
  2858.     glVertex2f(0.0F, 0.0F);
  2859.     glColor3f(1.0F, 0.9F, 0.3F);
  2860.     glVertex2f(1280.0F, 0.0F);
  2861.     glColor3f(0.6F, 0.1F, 0.9F);
  2862.     glVertex2f(1280.0F, 1024.0F);
  2863.     glColor3f(0.6F, 0.1F, 0.9F);
  2864.     glVertex2f(0.0F, 1024.0F);
  2865.     glEnd();
  2866.  
  2867.     glLineWidth(4.0F);
  2868.     glColor3f(0.0F, 0.0F, 0.0F);
  2869.     DrawString("     OpenGL     ", 172.0F, 602.0F);
  2870.     glLineWidth(3.0F);
  2871.     glColor3f(1.0F, 1.0F, 0.0F);
  2872.     DrawString("     OpenGL     ", 170.0F, 600.0F);
  2873.  
  2874.     glLineWidth(4.0F);
  2875.     glColor3f(0.0F, 0.0F, 0.0F);
  2876.     DrawString("    Viewperf    ", 172.0F, 477.0F);
  2877.     glLineWidth(3.0F);
  2878.     glColor3f(0.0F, 1.0F, 0.0F);
  2879.     DrawString("    Viewperf    ", 170.0F, 475.0F);
  2880.  
  2881.     glLineWidth(4.0F);
  2882.     glColor3f(0.0F, 0.0F, 0.0F);
  2883.     DrawString("Loading Data Set", 172.0F, 352.0F);
  2884.     glLineWidth(3.0F);
  2885.     glColor3f(0.0F, 0.7F, 1.0F);
  2886.     DrawString("Loading Data Set", 170.0F, 350.0F);
  2887.  
  2888.     if (renderDoubleBuffer && environ.bufConfig.doubleBuffer)
  2889.         auxSwapBuffers();
  2890.  
  2891.     /* Create thread blocks */
  2892.     eventblock.tb = (struct ThreadBlock *)calloc(eventblock.threads,
  2893.         sizeof(struct ThreadBlock));
  2894.  
  2895.     /*********************************************************************/
  2896.     /*                                                                   */
  2897.     /*                        Read Data Set in                           */
  2898.     /*                                                                   */
  2899.     /*********************************************************************/
  2900.  
  2901. #ifdef SEARCHPATH
  2902.     if (inputmode != NOINPUT)
  2903.     {
  2904.         char* objpath = getenv("VPGEOMPATH");
  2905.         char* dataPath;
  2906.         char  filenameptr[512];
  2907.         char* defaultPath = ".:./data/geometry/object:./data/geometry/mesh:/";
  2908.         if (objpath == 0)
  2909.             objpath = defaultPath;
  2910.         else 
  2911.             if (*objpath == 0)
  2912.                 objpath = defaultPath;
  2913.         if (objnameptr)
  2914.         {
  2915.             if (inputmode == MESHINPUT)
  2916.             {
  2917.                 /* Look for objnameptr file in objpath */
  2918.                 strcpy(filenameptr, objnameptr);
  2919.                 strcat(filenameptr, extension[4]);
  2920.                 dataPath = SearchPath(objpath, filenameptr);
  2921.                 if (dataPath == NULL)
  2922.                 {
  2923.                     FATAL_ERROR("Couldn't open mesh file\n");
  2924.                 }
  2925.             }
  2926.             else 
  2927.             {
  2928.                 /* Look for three files */
  2929.                 for (i=0; i<3; i++)
  2930.                 {
  2931.                     strcpy(filenameptr, objnameptr);
  2932.                     strcat(filenameptr, extension[i]);
  2933.                     dataPath = SearchPath(objpath, filenameptr);
  2934.                     if (dataPath == NULL)
  2935.                     {
  2936.                         fprintf(stdout, "%s\n", filenameptr);
  2937.                         FATAL_ERROR("Couldn't open input file\n");
  2938.                     }
  2939.                 }
  2940.             }
  2941.             /* Add dataPath to the beginning of objnameptr */
  2942.             strcat(dataPath, "/");
  2943.             strcpy(objnameptr, strcat(dataPath, objnameptr));
  2944.         }
  2945.     }
  2946. #endif
  2947.  
  2948.     switch (inputmode) {
  2949.     case NOINPUT:
  2950.         fprintf(stderr, "No input file specified\n");
  2951.         exit(0);
  2952.         break;
  2953.  
  2954.     case POLYGONINPUT:
  2955.         polygoninput(objnameptr, &eventblock);
  2956.         if (texturemode)
  2957.             param_poly(&eventblock);
  2958.         break;
  2959.  
  2960.     case MESHINPUT:
  2961.         meshinput(objnameptr, &eventblock);
  2962.         if (texturemode)
  2963.             param_mesh(&eventblock);
  2964.         break;
  2965.  
  2966.     case TRIINPUT:
  2967.         triquadinput(objnameptr, 3, &eventblock);
  2968.         if (texturemode)
  2969.             param_poly(&eventblock);
  2970.         break;
  2971.  
  2972.     case QUADINPUT:
  2973.         triquadinput(objnameptr, 4, &eventblock);
  2974.         if (texturemode)
  2975.             param_poly(&eventblock);
  2976.         break;
  2977.     }
  2978.  
  2979.     if (walkthrumode) {
  2980.     walkthruinput(objnameptr, &eventblock);
  2981.     }
  2982.  
  2983.     /*********************************************************************/
  2984.     /*                                                                   */
  2985.     /*                      Output test info                             */
  2986.     /*                                                                   */
  2987.     /*********************************************************************/
  2988.  
  2989.  
  2990.     /*
  2991.          * Viewperf program information
  2992.          */
  2993.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  2994.         "Viewperf Version", VERSION);
  2995.  
  2996.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  2997.         "Viewperf Arguments", cmdln);
  2998.  
  2999.     /*
  3000.          * Test Environment Information
  3001.          */
  3002.     PrintEnvironment(stdout, &environ, NULL, leader, nameWidth, NULL);
  3003.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3004.         "Visual Selection Criteria", txcriteria);
  3005.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3006.         "Number of Execution Threads", eventblock.threads);
  3007.  
  3008.     /*
  3009.          * General viewperf test information
  3010.          */
  3011.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3012.         "Geometry File", objnameptr);
  3013.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3014.         "Input Mode", inputmodetx[ inputmode ]);
  3015.     fprintf(stdout, "%s%*s%f\n", leader, nameWidth,
  3016.         "Minimum Test Period", eventblock.minperiod);
  3017.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3018.         "Number of Frames", eventblock.numframes);
  3019.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3020.         "Number of Primitives", renderblock.np);
  3021.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3022.         "Number of Vertices per Frame", vertsperframe);
  3023.     fprintf(stdout, "%s%*s%f\n", leader, nameWidth,
  3024.         "Number of Vertices per Primitive",
  3025.         ((GLfloat) vertsperframe) / ((GLfloat) renderblock.np));
  3026.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3027.         "Toggle Mode", txtoggle);
  3028.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3029.         "Batching Count", numtobatch);
  3030.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3031.         "Render Mode", rendermodetext[rendermode]);
  3032.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3033.         "Color per", txcolormode);
  3034.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3035.         "Orthographic Projection", falsetrue[orthomode]);
  3036.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3037.         "Display List", falsetrue[displaylistmode]);
  3038.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3039.         "Clip Geometry", falsetrue[clipmode]);
  3040.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3041.         "Walkthrough Mode", falsetrue[walkthrumode]);
  3042.  
  3043.     /*
  3044.          * Polygon information
  3045.          */
  3046.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3047.         "Back Face Cull", falsetrue[backfacemode]);
  3048.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3049.         "Front Face Cull", falsetrue[frontfacemode]);
  3050.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3051.         "Front Polygon Mode", txpmf);
  3052.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3053.         "Back Polygon Mode", txpmb);
  3054.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3055.         "Polygon Stipple Enable", falsetrue[polystipplemode]);
  3056.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3057.         "Polygon Antialiasing Enable", falsetrue[polysmoothmode]);
  3058.  
  3059.     /*
  3060.          * Line information
  3061.          */
  3062.     fprintf(stdout, "%s%*s%f\n", leader, nameWidth,
  3063.         "Line Width", linewidthmode);
  3064.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3065.         "Line Stipple Enable", falsetrue[linestipplemode]);
  3066.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3067.         "Line Antialiasing Enable", falsetrue[linesmoothmode]);
  3068.  
  3069.     /*
  3070.          * Lighting/Shading information
  3071.          */
  3072.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3073.         "Number of Infinite Lights", numInfiniteLights);
  3074.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3075.         "Number of Local Lights", numLocalLights);
  3076.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3077.         "Color Material Enable", falsetrue[(int)cmenable]);
  3078.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3079.         "Color Material Face", cmfaceString);
  3080.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3081.         "Color Material Mode", cmmodeString);
  3082.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3083.         "Facet Normals", falsetrue[facetnormalmode]);
  3084.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3085.         "Two Sided Lighting Enable", falsetrue[(int)lighttwoside]);
  3086.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3087.         "Local Viewer Enable", falsetrue[(int)localviewmode]);
  3088.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3089.         "Flat Shading", falsetrue[shademodelmode==GL_FLAT]);
  3090.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3091.         "Fog Enable", falsetrue[fogmode]);
  3092.  
  3093.     /*
  3094.          * Texturing information
  3095.          */
  3096.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3097.         "Texture Enable", falsetrue[texturemode]);
  3098.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3099.         "Texture Generation Mode", texture_generation_mode[texgenmode]);
  3100.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3101.         "Texture File", txfile);
  3102.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3103.         "Texture Minification Filter", txmin);
  3104.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3105.         "Texture Magnification Filter", txmag);
  3106.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3107.         "Texture Environment Mode", txenv);
  3108.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3109.         "Texture Components", numcomp);
  3110.  
  3111.  
  3112.     /*
  3113.          * Fragment Rasterization Information
  3114.          */
  3115.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3116.         "Depth Test Enable", falsetrue[zbuffermode]);
  3117.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3118.         "Blend Enable", falsetrue[blendmode]);
  3119.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3120.         "Source Blend Function", txsblendfunc);
  3121.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3122.         "Destination Blend Function", txdblendfunc);
  3123.     fprintf(stdout, "%s%*s%s\n", leader, nameWidth,
  3124.         "Dithering Enable", falsetrue[dithermode]);
  3125.     fprintf(stdout, "%s%*s%f\n", leader, nameWidth,
  3126.         "Motion Blur Amount", blur_amount);
  3127.     fprintf(stdout, "%s%*s%d\n", leader, nameWidth,
  3128.         "Full Scene Antialiasing Redraws", fsaredraw);
  3129.     fprintf(stdout, "%s%*s%f\n", leader, nameWidth,
  3130.         "Full Scene Antialiasing Jitter Amount", fsajitter);
  3131.  
  3132.     FreeEnvironmentData(&environ);
  3133.  
  3134.     /*********************************************************************/
  3135.     /*                                                                   */
  3136.     /*  Compute address into jump table for each renderer                */
  3137.     /*                                                                   */
  3138.     /*********************************************************************/
  3139.  
  3140.     eventblock.teststring = desc;
  3141.  
  3142.     rfindex.word = 0;
  3143.     rfindex.bits.Texture = texturemode;
  3144.  
  3145.     switch (inputmode)
  3146.     {
  3147.     case MESHINPUT:
  3148.         switch (rendermode)
  3149.         {
  3150.         case POLYGONmode:
  3151.         case TFANmode:
  3152.         case TRImode:
  3153.         case QUADmode:
  3154.             fprintf(stderr, "Rendermode %s not available for mesh objects\n",
  3155.                 rendermodetext[rendermode]);
  3156.             exit(0);
  3157.             break;
  3158.         case POINTmode:
  3159.             renderblock.mode = GL_POINTS;
  3160.             break;
  3161.         case VECTORmode:
  3162.             renderblock.mode = GL_LINES;
  3163.             break;
  3164.         case LINEmode:
  3165.             renderblock.mode = GL_LINE_STRIP;
  3166.             break;
  3167.         case TMESHmode:
  3168.             renderblock.mode = GL_TRIANGLE_STRIP; /* was GL_TRIANGLE_STRIP */
  3169.             break;
  3170.         }
  3171.         if (blendmode || polysmoothmode)
  3172.         {
  3173.             renderblock.ColorP = glColor4fv;
  3174. #ifdef FUNCTION_CALLS
  3175.             rfindex.bits.ColorVectorLength = COLOR4mode;
  3176. #endif
  3177.         }
  3178.         else 
  3179.         {
  3180.             renderblock.ColorP = glColor3fv;
  3181. #ifdef FUNCTION_CALLS
  3182.             rfindex.bits.ColorVectorLength = COLOR3mode;
  3183. #endif
  3184.         }
  3185.         if (togglemode)
  3186.         {
  3187.             if (rendermode == VECTORmode)
  3188.                 rfindex.bits.RenderMode = BM_EXTERNAL_BY_TWO;
  3189.             else
  3190.                 rfindex.bits.RenderMode = BM_EXTERNAL;
  3191.             if (togglelinewidthmode)
  3192.             {
  3193.                 renderblock.externfunc = toggle_linewidth;
  3194.             }
  3195.             else if (togglematrixmode)
  3196.             {
  3197.                 renderblock.externfunc = toggle_matrix;
  3198.             } else {
  3199.                 renderblock.externfunc = toggle_capability;
  3200.             }
  3201.         } else {
  3202.             rfindex.bits.RenderMode = BatchTable[rendermode];
  3203.         }
  3204.         rfindex.bits.Color = colormode;
  3205.         if (numInfiniteLights + numLocalLights > 0) {
  3206.             if (facetnormalmode)
  3207.                 rfindex.bits.Normal = FACET_NORMmode;
  3208.             else
  3209.                 rfindex.bits.Normal = VERTEX_NORMmode;
  3210.         } else {
  3211.             rfindex.bits.Normal = NO_NORMmode;
  3212.         }
  3213.         eventblock.func = MeshTable[rfindex.word];
  3214.  
  3215.         /* Calculate per thread input data */
  3216.         k = eventblock.rb->np / eventblock.threads;
  3217.         tb = eventblock.tb;
  3218.         for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++) {
  3219.             tb->np = k;
  3220.             tb->msh = &eventblock.rb->msh[thread * k];
  3221.         }
  3222.         tb->np = eventblock.rb->np - (thread * k);
  3223.         tb->msh = &eventblock.rb->msh[thread * k];
  3224.         break;
  3225.  
  3226.  
  3227.     case POLYGONINPUT:
  3228.         switch (rendermode)
  3229.         {
  3230.         case TMESHmode:
  3231.         case TRImode:
  3232.         case QUADmode:
  3233.             fprintf(stderr, "Rendermode %s not available for polygonal objects\n", 
  3234.                 rendermodetext[rendermode]);
  3235.             exit(0);
  3236.             break;
  3237.         case POINTmode:
  3238.             renderblock.mode = GL_POINTS;
  3239.             break;
  3240.         case VECTORmode:
  3241.             renderblock.mode = GL_LINES;
  3242.             break;
  3243.         case LINEmode:
  3244.             renderblock.mode = GL_LINE_LOOP;
  3245.             break;
  3246.         case POLYGONmode:
  3247.             renderblock.mode = GL_POLYGON;
  3248.             break;
  3249.         case TFANmode:
  3250.             renderblock.mode = GL_TRIANGLE_FAN;
  3251.             break;
  3252.         }
  3253.         if (blendmode || polysmoothmode)
  3254.         {
  3255.             renderblock.ColorP = glColor4fv;
  3256. #ifdef FUNCTION_CALLS
  3257.             rfindex.bits.ColorVectorLength = COLOR4mode;  
  3258. #endif
  3259.         }
  3260.         else 
  3261.         {
  3262.             renderblock.ColorP = glColor3fv;
  3263. #ifdef FUNCTION_CALLS
  3264.             rfindex.bits.ColorVectorLength = COLOR3mode; 
  3265. #endif
  3266.         }
  3267.         if (togglemode)
  3268.         {
  3269.             if (rendermode == VECTORmode)
  3270.                 rfindex.bits.RenderMode = BM_EXTERNAL_BY_TWO;
  3271.             else
  3272.                 rfindex.bits.RenderMode = BM_EXTERNAL;
  3273.             if (togglelinewidthmode)
  3274.             {
  3275.                 renderblock.externfunc = toggle_linewidth;
  3276.             }
  3277.             else 
  3278.                 if (togglematrixmode)
  3279.                 {
  3280.                     renderblock.externfunc = toggle_matrix;
  3281.                 }
  3282.                 else 
  3283.                 {
  3284.                     renderblock.externfunc = toggle_capability;
  3285.                 }
  3286.  
  3287.             /* Calculate per thread input data */
  3288.             k = eventblock.rb->np / eventblock.threads;
  3289.             tb = eventblock.tb;
  3290.             for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3291.             {
  3292.                 tb->np = k;
  3293.                 tb->ply = &eventblock.rb->ply[thread * k];
  3294.             }
  3295.             tb->np = eventblock.rb->np - (thread * k);
  3296.             tb->ply = &eventblock.rb->ply[thread * k];
  3297.  
  3298.         }
  3299.         else 
  3300.         {
  3301.             if (batchmode)
  3302.             {
  3303.  
  3304.                 /* Calculate per thread input data */
  3305.                 k = eventblock.rb->np / eventblock.threads;
  3306.                 tb = eventblock.tb;
  3307.                 for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3308.                 {
  3309.                     tb->np = k;
  3310.                     tb->ply = &eventblock.rb->ply[thread * k];
  3311.                     if(numtobatch >= tb->np)
  3312.                     {
  3313.                         tb->batchnum = tb->np;
  3314.                         tb->batchgroups = 1;
  3315.                         tb->batchleftovers = 0;
  3316.                     }
  3317.                     else 
  3318.                     {
  3319.                         tb->batchnum = numtobatch;
  3320.                         tb->batchgroups = tb->np / numtobatch;
  3321.                         tb->batchleftovers = tb->np % numtobatch;
  3322.                     }
  3323.                 }
  3324.                 tb->np = eventblock.rb->np - (thread * k);
  3325.                 tb->ply = &eventblock.rb->ply[thread * k];
  3326.                 if(numtobatch >= tb->np)
  3327.                 {
  3328.                     tb->batchnum = tb->np;
  3329.                     tb->batchgroups = 1;
  3330.                     tb->batchleftovers = 0;
  3331.                 }
  3332.                 else 
  3333.                 {
  3334.                     tb->batchnum = numtobatch;
  3335.                     tb->batchgroups = tb->np / numtobatch;
  3336.                     tb->batchleftovers = tb->np % numtobatch;
  3337.                 }
  3338.  
  3339.                 rfindex.bits.RenderMode = BatchTable[rendermode];
  3340.  
  3341.             }
  3342.             else 
  3343.             {
  3344.                 if (rendermode == VECTORmode)
  3345.                 {
  3346.  
  3347.                     /* Calculate per thread input data */
  3348.                     k = eventblock.rb->np / eventblock.threads;
  3349.                     tb = eventblock.tb;
  3350.                     for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3351.                     {
  3352.                         tb->np = k;
  3353.                         tb->ply = &eventblock.rb->ply[thread * k];
  3354.                         tb->batchnum = 1;
  3355.                         tb->batchgroups = tb->np;
  3356.                         tb->batchleftovers = 0;
  3357.                     }
  3358.                     tb->np = eventblock.rb->np - (thread * k);
  3359.                     tb->ply = &eventblock.rb->ply[thread * k];
  3360.                     tb->batchnum = 1;
  3361.                     tb->batchgroups = tb->np;
  3362.                     tb->batchleftovers = 0;
  3363.                     rfindex.bits.RenderMode = BM_BATCH_BY_TWO;
  3364.                 }
  3365.                 else 
  3366.                 {
  3367.  
  3368.                     /* Calculate per thread input data */
  3369.                     k = eventblock.rb->np / eventblock.threads;
  3370.                     tb = eventblock.tb;
  3371.                     for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3372.                     {
  3373.                         tb->np = k;
  3374.                         tb->ply = &eventblock.rb->ply[thread * k];
  3375.                     }
  3376.                     tb->np = eventblock.rb->np - (thread * k);
  3377.                     tb->ply = &eventblock.rb->ply[thread * k];
  3378.                     rfindex.bits.RenderMode = BM_NO_BATCH;
  3379.                 }
  3380.             }
  3381.         }
  3382.         rfindex.bits.Color = colormode;
  3383.         if (numInfiniteLights + numLocalLights > 0)
  3384.         {
  3385.             if (facetnormalmode)
  3386.                 rfindex.bits.Normal = FACET_NORMmode;
  3387.             else
  3388.                 rfindex.bits.Normal = VERTEX_NORMmode;
  3389.         }
  3390.         else 
  3391.         {
  3392.             rfindex.bits.Normal = NO_NORMmode;
  3393.         }
  3394.         eventblock.func = PolyTable[rfindex.word];
  3395.         break;
  3396.     case TRIINPUT:
  3397.         switch (rendermode)
  3398.         {
  3399.         case TMESHmode:
  3400.         case QUADmode:
  3401.         case POLYGONmode:
  3402.             fprintf(stderr, "Rendermode %s not available for Triangle objects\n", 
  3403.                 rendermodetext[rendermode]);
  3404.             exit(0);
  3405.             break;
  3406.         case POINTmode:
  3407.             renderblock.mode = GL_POINTS;
  3408.             break;
  3409.         case VECTORmode:
  3410.             renderblock.mode = GL_LINES;
  3411.             break;
  3412.         case LINEmode:
  3413.             renderblock.mode = GL_LINE_LOOP;
  3414.             break;
  3415.         case TRImode:
  3416.             renderblock.mode = GL_TRIANGLES;
  3417.             break;
  3418.         case TFANmode:
  3419.             renderblock.mode = GL_TRIANGLE_FAN;
  3420.             break;
  3421.         }
  3422.         if (blendmode || polysmoothmode)
  3423.         {
  3424.             renderblock.ColorP = glColor4fv;
  3425. #ifdef FUNCTION_CALLS
  3426.             rfindex.bits.ColorVectorLength = COLOR4mode; 
  3427. #endif
  3428.         }
  3429.         else 
  3430.         {
  3431.             renderblock.ColorP = glColor3fv;
  3432. #ifdef FUNCTION_CALLS
  3433.             rfindex.bits.ColorVectorLength = COLOR3mode; 
  3434. #endif
  3435.         }
  3436.         if (togglemode)
  3437.         {
  3438.             if (rendermode == VECTORmode)
  3439.                 rfindex.bits.RenderMode = BM_EXTERNAL_BY_TWO;
  3440.             else
  3441.                 rfindex.bits.RenderMode = BM_EXTERNAL;
  3442.             if (togglelinewidthmode)
  3443.             {
  3444.                 renderblock.externfunc = toggle_linewidth;
  3445.             }
  3446.             else 
  3447.                 if (togglematrixmode)
  3448.                 {
  3449.                     renderblock.externfunc = toggle_matrix;
  3450.                 }
  3451.                 else 
  3452.                 {
  3453.                     renderblock.externfunc = toggle_capability;
  3454.                 }
  3455.  
  3456.             /* Calculate per thread input data */
  3457.             k = eventblock.rb->np / eventblock.threads;
  3458.             tb = eventblock.tb;
  3459.             for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3460.             {
  3461.                 tb->np = k;
  3462.                 tb->ply = &eventblock.rb->ply[thread * k];
  3463.             }
  3464.             tb->np = eventblock.rb->np - (thread * k);
  3465.             tb->ply = &eventblock.rb->ply[thread * k];
  3466.         }
  3467.         else 
  3468.         {
  3469.             if (batchmode)
  3470.             {
  3471.                 /* Calculate per thread input data */
  3472.                 k = eventblock.rb->np / eventblock.threads;
  3473.                 tb = eventblock.tb;
  3474.                 for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3475.                 {
  3476.                     tb->np = k;
  3477.                     tb->ply = &eventblock.rb->ply[thread * k];
  3478.                     if(numtobatch >= tb->np)
  3479.                     {
  3480.                         tb->batchnum = tb->np;
  3481.                         tb->batchgroups = 1;
  3482.                         tb->batchleftovers = 0;
  3483.                     }
  3484.                     else 
  3485.                     {
  3486.                         tb->batchnum = numtobatch;
  3487.                         tb->batchgroups = tb->np / numtobatch;
  3488.                         tb->batchleftovers = tb->np % numtobatch;
  3489.                     }
  3490.                 }
  3491.                 tb->np = eventblock.rb->np - (thread * k);
  3492.                 tb->ply = &eventblock.rb->ply[thread * k];
  3493.                 if(numtobatch >= tb->np)
  3494.                 {
  3495.                     tb->batchnum = tb->np;
  3496.                     tb->batchgroups = 1;
  3497.                     tb->batchleftovers = 0;
  3498.                 }
  3499.                 else 
  3500.                 {
  3501.                     tb->batchnum = numtobatch;
  3502.                     tb->batchgroups = tb->np / numtobatch;
  3503.                     tb->batchleftovers = tb->np % numtobatch;
  3504.                 }
  3505.                 rfindex.bits.RenderMode = BatchTable[rendermode];
  3506.             }
  3507.             else 
  3508.             {
  3509.                 if (rendermode == VECTORmode)
  3510.                 {
  3511.                     /* Calculate per thread input data */
  3512.                     k = eventblock.rb->np / eventblock.threads;
  3513.                     tb = eventblock.tb;
  3514.                     for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3515.                     {
  3516.                         tb->np = k;
  3517.                         tb->ply = &eventblock.rb->ply[thread * k];
  3518.                         tb->batchnum = 1;
  3519.                         tb->batchgroups = tb->np;
  3520.                         tb->batchleftovers = 0;
  3521.                     }
  3522.                     tb->np = eventblock.rb->np - (thread * k);
  3523.                     tb->ply = &eventblock.rb->ply[thread * k];
  3524.                     tb->batchnum = 1;
  3525.                     tb->batchgroups = tb->np;
  3526.                     tb->batchleftovers = 0;
  3527.                     rfindex.bits.RenderMode = BM_BATCH_BY_TWO;
  3528.                 }
  3529.                 else 
  3530.                 {
  3531.  
  3532.                     /* Calculate per thread input data */
  3533.                     k = eventblock.rb->np / eventblock.threads;
  3534.                     tb = eventblock.tb;
  3535.                     for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3536.                     {
  3537.                         tb->np = k;
  3538.                         tb->ply = &eventblock.rb->ply[thread * k];
  3539.                     }
  3540.                     tb->np = eventblock.rb->np - (thread * k);
  3541.                     tb->ply = &eventblock.rb->ply[thread * k];
  3542.                     rfindex.bits.RenderMode = BM_NO_BATCH;
  3543.                 }
  3544.             }
  3545.         }
  3546.         rfindex.bits.Color = colormode;
  3547.         if (numInfiniteLights + numLocalLights > 0)
  3548.         {
  3549.             if (facetnormalmode)
  3550.                 rfindex.bits.Normal = FACET_NORMmode;
  3551.             else
  3552.                 rfindex.bits.Normal = VERTEX_NORMmode;
  3553.         }
  3554.         else 
  3555.         {
  3556.             rfindex.bits.Normal = NO_NORMmode;
  3557.         }
  3558.         eventblock.func = TriTable[rfindex.word];
  3559.         break;
  3560.     case QUADINPUT:
  3561.         switch (rendermode)
  3562.         {
  3563.         case TMESHmode:
  3564.         case TRImode:
  3565.         case POLYGONmode:
  3566.             fprintf(stderr, "Rendermode %s not available for Quad objects\n", 
  3567.                 rendermodetext[rendermode]);
  3568.             exit(0);
  3569.             break;
  3570.         case POINTmode:
  3571.             renderblock.mode = GL_POINTS;
  3572.             break;
  3573.         case VECTORmode:
  3574.             renderblock.mode = GL_LINES;
  3575.             break;
  3576.         case LINEmode:
  3577.             renderblock.mode = GL_LINE_LOOP;
  3578.             break;
  3579.         case QUADmode:
  3580.             renderblock.mode = GL_QUADS;
  3581.             break;
  3582.         case TFANmode:
  3583.             renderblock.mode = GL_TRIANGLE_FAN;
  3584.             break;
  3585.         }
  3586.         if (blendmode || polysmoothmode)
  3587.         {
  3588.             renderblock.ColorP = glColor4fv;
  3589. #ifdef FUNCTION_CALLS
  3590.             rfindex.bits.ColorVectorLength = COLOR4mode; 
  3591. #endif
  3592.         }
  3593.         else 
  3594.         {
  3595.             renderblock.ColorP = glColor3fv;
  3596. #ifdef FUNCTION_CALLS
  3597.             rfindex.bits.ColorVectorLength = COLOR3mode;  
  3598. #endif
  3599.         }
  3600.         if (togglemode)
  3601.         {
  3602.             if (rendermode == VECTORmode)
  3603.                 rfindex.bits.RenderMode = BM_EXTERNAL_BY_TWO;
  3604.             else
  3605.                 rfindex.bits.RenderMode = BM_EXTERNAL;
  3606.             if (togglelinewidthmode)
  3607.             {
  3608.                 renderblock.externfunc = toggle_linewidth;
  3609.             }
  3610.             else 
  3611.                 if (togglematrixmode)
  3612.                 {
  3613.                     renderblock.externfunc = toggle_matrix;
  3614.                 }
  3615.                 else 
  3616.                 {
  3617.                     renderblock.externfunc = toggle_capability;
  3618.                 }
  3619.  
  3620.             /* Calculate per thread input data */
  3621.             k = eventblock.rb->np / eventblock.threads;
  3622.             tb = eventblock.tb;
  3623.             for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3624.             {
  3625.                 tb->np = k;
  3626.                 tb->ply = &eventblock.rb->ply[thread * k];
  3627.             }
  3628.             tb->np = eventblock.rb->np - (thread * k);
  3629.             tb->ply = &eventblock.rb->ply[thread * k];
  3630.         }
  3631.         else 
  3632.         {
  3633.             if (batchmode)
  3634.             {
  3635.                 /* Calculate per thread input data */
  3636.                 k = eventblock.rb->np / eventblock.threads;
  3637.                 tb = eventblock.tb;
  3638.                 for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3639.                 {
  3640.                     tb->np = k;
  3641.                     tb->ply = &eventblock.rb->ply[thread * k];
  3642.                     if(numtobatch >= tb->np)
  3643.                     {
  3644.                         tb->batchnum = tb->np;
  3645.                         tb->batchgroups = 1;
  3646.                         tb->batchleftovers = 0;
  3647.                     }
  3648.                     else 
  3649.                     {
  3650.                         tb->batchnum = numtobatch;
  3651.                         tb->batchgroups = tb->np / numtobatch;
  3652.                         tb->batchleftovers = tb->np % numtobatch;
  3653.                     }
  3654.                 }
  3655.                 tb->np = eventblock.rb->np - (thread * k);
  3656.                 tb->ply = &eventblock.rb->ply[thread * k];
  3657.                 if(numtobatch >= tb->np)
  3658.                 {
  3659.                     tb->batchnum = tb->np;
  3660.                     tb->batchgroups = 1;
  3661.                     tb->batchleftovers = 0;
  3662.                 }
  3663.                 else 
  3664.                 {
  3665.                     tb->batchnum = numtobatch;
  3666.                     tb->batchgroups = tb->np / numtobatch;
  3667.                     tb->batchleftovers = tb->np % numtobatch;
  3668.                 }
  3669.                 rfindex.bits.RenderMode = BatchTable[rendermode];
  3670.             }
  3671.             else 
  3672.             {
  3673.                 if (rendermode == VECTORmode)
  3674.                 {
  3675.                     /* Calculate per thread input data */
  3676.                     k = eventblock.rb->np / eventblock.threads;
  3677.                     tb = eventblock.tb;
  3678.                     for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3679.                     {
  3680.                         tb->np = k;
  3681.                         tb->ply = &eventblock.rb->ply[thread * k];
  3682.                         tb->batchnum = 1;
  3683.                         tb->batchgroups = tb->np;
  3684.                         tb->batchleftovers = 0;
  3685.                     }
  3686.                     tb->np = eventblock.rb->np - (thread * k);
  3687.                     tb->ply = &eventblock.rb->ply[thread * k];
  3688.                     tb->batchnum = 1;
  3689.                     tb->batchgroups = tb->np;
  3690.                     tb->batchleftovers = 0;
  3691.                     rfindex.bits.RenderMode = BM_BATCH_BY_TWO;
  3692.                 }
  3693.                 else 
  3694.                 {
  3695.  
  3696.                     /* Calculate per thread input data */
  3697.                     k = eventblock.rb->np / eventblock.threads;
  3698.                     tb = eventblock.tb;
  3699.                     for (thread = 0; thread < (eventblock.threads - 1); thread++, tb++)
  3700.                     {
  3701.                         tb->np = k;
  3702.                         tb->ply = &eventblock.rb->ply[thread * k];
  3703.                     }
  3704.                     tb->np = eventblock.rb->np - (thread * k);
  3705.                     tb->ply = &eventblock.rb->ply[thread * k];
  3706.                     rfindex.bits.RenderMode = BM_NO_BATCH;
  3707.                 }
  3708.             }
  3709.         }
  3710.         rfindex.bits.Color = colormode;
  3711.         if (numInfiniteLights + numLocalLights > 0)
  3712.         {
  3713.             if (facetnormalmode)
  3714.                 rfindex.bits.Normal = FACET_NORMmode;
  3715.             else
  3716.                 rfindex.bits.Normal = VERTEX_NORMmode;
  3717.         }
  3718.         else 
  3719.         {
  3720.             rfindex.bits.Normal = NO_NORMmode;
  3721.         }
  3722.         eventblock.func = QuadTable[rfindex.word];
  3723.         break;
  3724.     }
  3725.     eventblock.jitter = jitter;
  3726.     eventblock.redraws = fsaredraw;
  3727.     eventblock.blur_frames = blur_amount;
  3728.     eventblock.doubleBuffer = renderDoubleBuffer && environ.bufConfig.doubleBuffer;
  3729.     eventblock.clip = clipmode;
  3730.     eventblock.zbuffer = zbuffermode;
  3731.  
  3732.     /* Copy rest of RenderBlock information into ThreadBlock */
  3733.     tb = eventblock.tb;
  3734.     for (thread = 0; thread < eventblock.threads; thread++, tb++)
  3735.     {
  3736.         tb->mode = eventblock.rb->mode;
  3737.         tb->capability = eventblock.rb->capability;
  3738.         tb->ColorP = eventblock.rb->ColorP;
  3739.         tb->externfunc = eventblock.rb->externfunc;
  3740.         tb->vert = eventblock.rb->vert;
  3741.         tb->vnorm = eventblock.rb->vnorm;
  3742.         tb->texture = eventblock.rb->texture;
  3743.         tb->vcolor = eventblock.rb->vcolor;
  3744.     }
  3745.  
  3746.     /*********************************************************************/
  3747.     /*                                                                   */
  3748.     /*  Compute address into jump table for eventloop                    */
  3749.     /*                                                                   */
  3750.     /*********************************************************************/
  3751.  
  3752.     elindex.word = 0;
  3753.     elindex.bits.Walkthru = walkthrumode;
  3754.     elindex.bits.FSAA = fsantimode;
  3755.     elindex.bits.BlurMode = mblurmode;
  3756.     elindex.bits.DisplayList = displaylistmode;
  3757.  
  3758.     eventloop = EventTable[elindex.word];
  3759.  
  3760.     /*********************************************************************/
  3761.     /*                                                                   */
  3762.     /*  Load Texture Image                                               */
  3763.     /*                                                                   */
  3764.     /*********************************************************************/
  3765.  
  3766.     if (texturemode || texgenmode) {
  3767.         k = 0;
  3768.         do
  3769.         {
  3770.             fread(&header[k], 1, 1, texfile);
  3771.             ++k;
  3772.         }    while ((header[k-1] != 0) && (header[k-1] != 10));
  3773.  
  3774.         for (i = 0; i < k; i++)
  3775.             if (header[i] == ' ')
  3776.             {
  3777.                 header[i] = 0;
  3778.                 depth = &header[i+1];
  3779.                 break;
  3780.             }
  3781.  
  3782.         xpix = atoi(header);
  3783.         ypix = atoi(depth);
  3784.  
  3785.         numpix = xpix * ypix;
  3786.         Image = (unsigned char *) malloc ( numpix * 3 );
  3787.         TextureImage = (unsigned char *) malloc(numpix * numcomp);
  3788.  
  3789.         fread(Image, 3, numpix, texfile);
  3790.         fclose(texfile);
  3791.  
  3792.         switch (numcomp)
  3793.         {
  3794.         case 1 :
  3795.             i = 0;
  3796.             for (j = 0; j < numpix * 3; j += 3)
  3797.             {
  3798.                 TextureImage[i++] = Image[j+1];
  3799.             }
  3800.             break;
  3801.         case 2 :
  3802.             i = 0;
  3803.             for (j = 0; j < numpix * 3; j += 3)
  3804.             {
  3805.                 TextureImage[i++] = Image[j];
  3806.                 TextureImage[i++] = 0x77;
  3807.             }
  3808.             break;
  3809.         case 3 :
  3810.             i = 0;
  3811.             for (j = 0; j < numpix * 3; j += 3)
  3812.             {
  3813.                 TextureImage[i++] = Image[j];
  3814.                 TextureImage[i++] = Image[j+1];
  3815.                 TextureImage[i++] = Image[j+2];
  3816.             }
  3817.             break;
  3818.         case 4 :
  3819.             i = 0;
  3820.             for (j = 0; j < numpix * 3; j += 3)
  3821.             {
  3822.                 TextureImage[i++] = Image[j];
  3823.                 TextureImage[i++] = Image[j+1];
  3824.                 TextureImage[i++] = Image[j+2];
  3825.                 TextureImage[i++] = 0x77;
  3826.             }
  3827.             break;
  3828.         }
  3829.         free(Image);
  3830.     }
  3831.  
  3832.     /*********************************************************************/
  3833.     /*                                                                   */
  3834.     /*                     Begin Rendering                               */
  3835.     /*                                                                   */
  3836.     /*********************************************************************/
  3837.  
  3838. #ifdef WIN32
  3839.     eventblock.tb[0].dc = eventblock.display;
  3840.     eventblock.tb[0].rc = wglGetCurrentContext();
  3841. #endif
  3842.  
  3843.     /* Initialize the contexts in the reverse order so that this thread
  3844.      * ends up with its own context current.
  3845.      */
  3846. #ifdef MP
  3847.     for (thread = (eventblock.threads - 1); thread >= 0; thread--) {
  3848. #if defined(WIN32)
  3849.         if (eventblock.tb[thread].rc == NULL)
  3850.             eventblock.tb[thread].rc = wglCreateContext(eventblock.display);
  3851.         wglMakeCurrent(eventblock.display, eventblock.tb[thread].rc);
  3852. #elif defined(SOME_OTHER_OS)
  3853.         /* Put os specific code to:
  3854.             Create Context
  3855.             Make context current
  3856.         */
  3857. #endif
  3858. #endif
  3859.         if (linesmoothmode) {
  3860.             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  3861.             glEnable(GL_BLEND);
  3862.             glEnable(GL_LINE_SMOOTH);
  3863.         }
  3864.         if (polysmoothmode) {
  3865.             glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
  3866.             glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  3867.             glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
  3868.             glBlendFunc(sblendfunc, dblendfunc);
  3869.             glEnable(GL_BLEND);
  3870.             glEnable(GL_POLYGON_SMOOTH);
  3871.         }
  3872.         if (blendmode) {
  3873.             glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  3874.             glColor4f(1.0F, 1.0F, 1.0F, 0.5F);
  3875.             glBlendFunc(sblendfunc, dblendfunc);
  3876.             glEnable(GL_BLEND);
  3877.         } else {
  3878.             glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
  3879.             glColor3f(1.0F, 1.0F, 1.0F);
  3880.         }
  3881.  
  3882.         if (dithermode) {
  3883.             glEnable(GL_DITHER);
  3884.         } else {
  3885.             glDisable(GL_DITHER);
  3886.         }
  3887.  
  3888.         glPolygonMode(GL_FRONT, polymodefront);
  3889.         glPolygonMode(GL_BACK, polymodeback);
  3890.  
  3891.         if (linestipplemode) {
  3892.             glLineStipple(1, 0xf0f0);
  3893.             glEnable(GL_LINE_STIPPLE);
  3894.         }
  3895.  
  3896.         if (polystipplemode) {
  3897.             glPolygonStipple((const GLubyte *) stipple);
  3898.             glEnable(GL_POLYGON_STIPPLE);
  3899.         }
  3900.         glShadeModel(shademodelmode);
  3901.         if (zbuffermode) {
  3902.             glEnable(GL_DEPTH_TEST);
  3903.             glDepthFunc(GL_LESS);
  3904.             glDepthMask(GL_TRUE);
  3905.         } else {
  3906.             glDisable(GL_DEPTH_TEST);
  3907.             glDepthMask(GL_FALSE);
  3908.         }
  3909.         if (backfacemode) {
  3910.             glCullFace(GL_BACK);
  3911.             glEnable(GL_CULL_FACE);
  3912.         }
  3913.         if (frontfacemode) {
  3914.             glCullFace(GL_FRONT);
  3915.             glEnable(GL_CULL_FACE);
  3916.         }
  3917.         if (frontfacemode && backfacemode) {
  3918.             glCullFace(GL_FRONT_AND_BACK);
  3919.             glEnable(GL_CULL_FACE);
  3920.         }
  3921.         glLineWidth(linewidthmode);
  3922.         if (fogmode) {
  3923.             glFogf(GL_FOG_START, eventblock.trans[3] * ZTRANS_SCALE - maxdim);
  3924.             glFogf(GL_FOG_END, eventblock.trans[3] * ZTRANS_SCALE + maxdim);
  3925.             glFogf(GL_FOG_MODE, GL_LINEAR);
  3926.             glEnable(GL_FOG);
  3927.         }
  3928.  
  3929.         glMatrixMode(GL_PROJECTION);
  3930.         glLoadIdentity();
  3931.     if (walkthrumode) {
  3932.         if (orthomode) {
  3933.         /* This will NOT work well, need to do something else... */
  3934.             glOrtho(-maxdim / 1.1F, maxdim / 1.1F, -maxdim / 1.1F, maxdim / 1.1F,
  3935.                 trans[3] * ZTRANS_SCALE - maxdim, trans[3] * ZTRANS_SCALE + maxdim);
  3936.         } else {
  3937.         /* Quite arbitrary FOV, near and far planes, need something better */
  3938.             gluPerspective(60.0, environ.windowWidth/environ.windowHeight, 1.0, 1000.0);
  3939.         }
  3940.     } else {
  3941.         if (orthomode) {
  3942.             glOrtho(-maxdim / 1.1F, maxdim / 1.1F, -maxdim / 1.1F, maxdim / 1.1F,
  3943.                 trans[3] * ZTRANS_SCALE - maxdim, trans[3] * ZTRANS_SCALE + maxdim);
  3944.         } else {
  3945.             glFrustum(-maxdim / 1.6F, maxdim / 1.6F, -maxdim / 1.6F, maxdim / 1.6F, 
  3946.                 trans[3] * ZTRANS_SCALE - maxdim, trans[3] * ZTRANS_SCALE + maxdim);
  3947.         }
  3948.     }
  3949.  
  3950.         glMatrixMode(GL_MODELVIEW);
  3951.         glLoadIdentity();
  3952.  
  3953.         SetLightingState(numInfiniteLights, numLocalLights, localviewmode, lighttwoside, 
  3954.                          cmenable, cmface, cmmode, blendmode);
  3955.  
  3956.         if (texturemode || texgenmode) {
  3957.             switch (numcomp) {
  3958.             case 1:
  3959.                 if (gluBuild2DMipmaps(GL_TEXTURE_2D, numcomp, xpix, 
  3960.                     ypix, GL_LUMINANCE, GL_UNSIGNED_BYTE, TextureImage) != 0) {
  3961.                     fprintf(stderr, "Mipmaps didn't build\n");
  3962.                     exit(0);
  3963.                 }
  3964.                 break;
  3965.             case 2:
  3966.                 if (gluBuild2DMipmaps(GL_TEXTURE_2D, numcomp, xpix, 
  3967.                     ypix, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, TextureImage) != 0) {
  3968.                     fprintf(stderr, "Mipmaps didn't build\n");
  3969.                     exit(0);
  3970.                 }
  3971.                 break;
  3972.             case 3:
  3973.                 if (gluBuild2DMipmaps(GL_TEXTURE_2D, numcomp, xpix, 
  3974.                     ypix, GL_RGB, GL_UNSIGNED_BYTE, TextureImage) != 0) {
  3975.                     fprintf(stderr, "Mipmaps didn't build\n");
  3976.                     exit(0);
  3977.                 }
  3978.                 break;
  3979.             case 4:
  3980.                 if (gluBuild2DMipmaps(GL_TEXTURE_2D, numcomp, xpix, 
  3981.                     ypix, GL_RGBA, GL_UNSIGNED_BYTE, TextureImage) != 0) {
  3982.                     fprintf(stderr, "Mipmaps didn't build\n");
  3983.                     exit(0);
  3984.                 }
  3985.                 break;
  3986.             }
  3987.             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texenvmode);
  3988.             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magfilter);
  3989.             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);
  3990.             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  3991.             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  3992.             if(texgenmode) {
  3993.                 switch(texgenmode) {
  3994.                 case TXG_NO_TEX_GEN:
  3995.                     FATAL_ERROR("Hoseage has occurred in texture generation\n");
  3996.                     break;
  3997.                 case TXG_EYE_LINEAR:
  3998.                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); /* Was GL_EYE_LINEAR */
  3999.                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
  4000.                     break;
  4001.                 case TXG_OBJECT_LINEAR:
  4002.                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  4003.                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
  4004.                     break;
  4005.                 case TXG_SPHERE_MAP:
  4006.                     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  4007.                     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
  4008.                     break;
  4009.                 }
  4010.                 glEnable(GL_TEXTURE_GEN_S);
  4011.                 glEnable(GL_TEXTURE_GEN_T);
  4012.  
  4013.                 glMatrixMode(GL_TEXTURE);
  4014.                 glRotatef(180.0F, 0.0F, 0.0F, 1.0F);
  4015.                 glTranslatef(0.5F, 0.5F, 0.0F);
  4016.                 glScalef(1.0F / (maxdim * 2.0F), 1.0F / (maxdim * 2.0F), 1.0F / (maxdim * 2.0F));
  4017.                 glMatrixMode(GL_MODELVIEW);
  4018.             }
  4019.             glEnable(GL_TEXTURE_2D);
  4020.             glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  4021.         }
  4022. #ifdef MP
  4023.     }
  4024. #endif
  4025.  
  4026.     /*********************************************************************/
  4027.     /*                                                                   */
  4028.     /*  Run the tests by calling the eventloop                           */
  4029.     /*                                                                   */
  4030.     /*********************************************************************/
  4031.  
  4032.  
  4033. #ifdef MP
  4034.     tb = &eventblock.tb[1];
  4035.     for (thread = 1; thread < eventblock.threads; thread++, tb++)
  4036.     {
  4037. #if defined(WIN32)
  4038.         tb->startEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  4039.         tb->doneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  4040.         tb->threadHandle = CreateThread(NULL, 0,
  4041.             (LPTHREAD_START_ROUTINE)eventloop, (LPVOID)thread, 0,
  4042.             &tb->threadId);
  4043. #elif defined(SOME_OTHER_OS)
  4044.         /* Put os specific code to:
  4045.             Create synchronization events for each thread
  4046.             Create each thread
  4047.             Call eventloop() with thread number
  4048.         */
  4049. #endif
  4050.     }
  4051. #endif
  4052.  
  4053.     (*eventloop)(0);
  4054.  
  4055. #ifdef MP
  4056.     tb = &eventblock.tb[1];
  4057.     for (thread = 1; thread < eventblock.threads; thread++, tb++)
  4058.     {
  4059. #if defined(WIN32)
  4060.         TerminateThread(tb->threadHandle, 0);
  4061. #elif defined(SOME_OTHER_OS)
  4062.         /* Put os specific code to:
  4063.             Terminate threads
  4064.         */
  4065. #endif
  4066.     }
  4067. #endif
  4068.  
  4069.     fprintf(stdout, "=============================================================\n");
  4070.  
  4071. #ifdef WIN32
  4072.     fclose(LogFile);
  4073. #endif
  4074.  
  4075.     auxQuit();
  4076. }
  4077.  
  4078.  
  4079. #ifdef WIN32
  4080. int print_log (FILE *fo, const char *format, ...)
  4081. {
  4082.     int count;
  4083.     va_list args;
  4084.  
  4085.     va_start(args, format);
  4086.     count = vfprintf(LogFile, format, args);
  4087.     fflush(LogFile);
  4088.     va_end(args);
  4089.     return count;
  4090. }
  4091. #endif
  4092.  
  4093. #ifdef MP
  4094. int numProcessors ()
  4095. {
  4096. #if defined(WIN32)
  4097.     SYSTEM_INFO si;
  4098.     GetSystemInfo(&si);
  4099.     return (si.dwNumberOfProcessors);
  4100.  
  4101. #elif defined(SOME_OTHER_OS)
  4102.     /* Put os specific code to:
  4103.         Return number of processors                
  4104.     */
  4105. #endif
  4106. }
  4107. #endif
  4108.